Merge branch 'main' into feature-session-statebag

This commit is contained in:
westey
2026-02-11 10:49:08 +00:00
committed by GitHub
575 changed files with 14061 additions and 24017 deletions
@@ -123,7 +123,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
IAsyncEnumerable<AgentResponseUpdate> agentResponse =
messages is not null ?
agent.RunStreamingAsync([.. messages], null, runOptions, cancellationToken) :
agent.RunStreamingAsync([new ChatMessage(ChatRole.User, string.Empty)], null, runOptions, cancellationToken);
agent.RunStreamingAsync([], null, runOptions, cancellationToken);
await foreach (AgentResponseUpdate update in agentResponse.ConfigureAwait(false))
{
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
// Runtime Version: 18.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -10,16 +10,13 @@
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
internal partial class AddConversationMessageTemplate : ActionTemplate
{
/// <summary>
@@ -35,17 +32,8 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n\n/// <summary>\n/// Adds a new message to the specified agent conversation\n/// </" +
"summary>\ninternal sealed class ");
this.Write("\n/// <summary>\n/// Adds a new message to the specified agent conversation\n/// </s" +
"ummary>\ninternal sealed class ");
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
this.Write("Executor(FormulaSession session, WorkflowAgentProvider agentProvider) : ActionExe" +
"cutor(id: \"");
@@ -134,446 +122,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
@@ -803,116 +351,6 @@ this.Write(").ConfigureAwait(false);");
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
@@ -1,8 +1,12 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateRecordExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateStringExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/FormatMessageTemplate.tt" once="true" #>
/// <summary>
/// Adds a new message to the specified agent conversation
/// </summary>
@@ -9,11 +9,8 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using Microsoft.Agents.ObjectModel;
using System;
/// <summary>
@@ -27,17 +24,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -87,85 +73,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
@@ -310,601 +217,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,10 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateEnumExpressionTemplate.tt" once="true" #>
/// <summary>
/// Reset all the state for the targeted variable scope.
/// </summary>
@@ -9,11 +9,8 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,17 +24,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -182,746 +168,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,10 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.ObjectModel" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateBoolExpressionTemplate.tt" once="true" #>
/// <summary>
/// Conditional branching similar to an if / elseif / elseif / else chain.
/// </summary>
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
// Runtime Version: 18.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,17 +9,14 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
internal partial class CopyConversationMessagesTemplate : ActionTemplate
{
/// <summary>
@@ -27,16 +24,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -103,554 +90,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
@@ -881,46 +320,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,11 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ import namespace="Microsoft.Extensions.AI" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateStringExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateValueExpressionTemplate.tt" once="true" #>
/// <summary>
/// Copies one or more messages into the specified agent conversation.
/// </summary>
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
// Runtime Version: 18.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,17 +9,13 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
internal partial class CreateConversationTemplate : ActionTemplate
{
/// <summary>
@@ -27,19 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -91,825 +74,5 @@ this.Write("\n ");
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,8 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
/// <summary>
/// Creates a new conversation and stores the identifier value to the "<#= this.Model.ConversationId #>" variable.
/// </summary>
@@ -9,11 +9,6 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,21 +22,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n/// <summary>\n/// Modify items in a list\n/// </summary>\ninternal sealed class ");
@@ -53,853 +33,5 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
" {\n return default;\n }\n}");
return this.GenerationEnvironment.ToString();
}
void AssignVariable(PropertyPath targetVariable, string valueVariable, bool tightFormat = false)
{
if (targetVariable is not null)
{
this.Write("\n await context.QueueStateUpdateAsync(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableName(targetVariable)));
this.Write("\", value: ");
this.Write(this.ToStringHelper.ToStringWithCulture(valueVariable));
this.Write(", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableScope(targetVariable)));
this.Write("\").ConfigureAwait(false);");
if (!tightFormat)
{
this.Write("\n ");
}
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,6 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
/// <summary>
/// Modify items in a list
/// </summary>
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,18 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -143,675 +127,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
@@ -921,46 +236,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,9 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateValueExpressionTemplate.tt" once="true" #>
/// <summary>
/// Loops over a list assignign the loop variable to "<#= this.Model.Value #>" variable.
/// </summary>
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
// Runtime Version: 18.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,17 +9,16 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using System.Collections.Generic;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
internal partial class InvokeAzureAgentTemplate : ActionTemplate
{
/// <summary>
@@ -37,13 +36,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n/// <summary>\n/// Invokes an agent to process messages and return a response wit" +
"hin a conversation context.\n/// </summary>\ninternal sealed class ");
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
@@ -191,259 +183,6 @@ this.Write(").ConfigureAwait(false);");
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
@@ -552,114 +291,6 @@ this.Write(").ConfigureAwait(false);");
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
@@ -780,156 +411,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,14 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ import namespace="Microsoft.Extensions.AI" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateBoolExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateListExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateStringExpressionTemplate.tt" once="true" #>
/// <summary>
/// Invokes an agent to process messages and return a response within a conversation context.
/// </summary>
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,19 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -112,825 +95,5 @@ this.Write("\n ");
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,8 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
/// <summary>
/// Parses a string or untyped value to the provided data type. When the input is a string, it will be treated as JSON.
/// </summary>
@@ -9,11 +9,6 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,21 +22,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n/// <summary>\n/// Request input.\n/// </summary>\ninternal sealed class ");
@@ -53,853 +33,5 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
" {\n return default;\n }\n}");
return this.GenerationEnvironment.ToString();
}
void AssignVariable(PropertyPath targetVariable, string valueVariable, bool tightFormat = false)
{
if (targetVariable is not null)
{
this.Write("\n await context.QueueStateUpdateAsync(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableName(targetVariable)));
this.Write("\", value: ");
this.Write(this.ToStringHelper.ToStringWithCulture(valueVariable));
this.Write(", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableScope(targetVariable)));
this.Write("\").ConfigureAwait(false);");
if (!tightFormat)
{
this.Write("\n ");
}
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,6 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
/// <summary>
/// Request input.
/// </summary>
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,19 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -87,825 +70,5 @@ this.Write("\n ");
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,8 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
/// <summary>
/// Resets the value of the "<#= this.Model.Variable #>" variable, potentially causing re-evaluation
/// of the default value, question or action that provides the value to this variable.
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,17 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -93,446 +78,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
@@ -761,156 +306,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,10 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateRecordExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateStringExpressionTemplate.tt" once="true" #>
/// <summary>
/// Retrieves a list of messages from an agent conversation.
/// </summary>
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
// Runtime Version: 18.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,17 +9,15 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.ObjectModel;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
internal partial class RetrieveConversationMessagesTemplate : ActionTemplate
{
/// <summary>
@@ -37,13 +35,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n/// <summary>\n/// Retrieves a specific message from an agent conversation.\n/// <" +
"/summary>\ninternal sealed class ");
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
@@ -108,85 +99,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
@@ -440,114 +352,6 @@ this.Write(").ConfigureAwait(false);");
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
@@ -776,156 +580,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,14 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateEnumExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateIntExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateRecordExpressionTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateStringExpressionTemplate.tt" once="true" #>
/// <summary>
/// Retrieves a specific message from an agent conversation.
/// </summary>
@@ -10,10 +10,7 @@
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,18 +24,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -71,822 +56,15 @@ if (this.Model.Activity is MessageActivityTemplate messageActivity)
}
this.Write("\n );\n AgentResponse response = new([new ChatMessage(ChatRole" +
".Assistant, activityText)]);\n await context.AddEventAsync(new AgentRes" +
"ponseEvent(this.Id, response)).ConfigureAwait(false);");
this.Write("\n );\n AgentResponse response = new([new ChatMessage(ChatRole.As" +
"sistant, activityText)]);\n await context.AddEventAsync(new AgentResponseE" +
"vent(this.Id, response)).ConfigureAwait(false);");
}
this.Write("\n\n return default;\n }\n}");
return this.GenerationEnvironment.ToString();
}
void AssignVariable(PropertyPath targetVariable, string valueVariable, bool tightFormat = false)
{
if (targetVariable is not null)
{
this.Write("\n await context.QueueStateUpdateAsync(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableName(targetVariable)));
this.Write("\", value: ");
this.Write(this.ToStringHelper.ToStringWithCulture(valueVariable));
this.Write(", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(VariableScope(targetVariable)));
this.Write("\").ConfigureAwait(false);");
if (!tightFormat)
{
this.Write("\n ");
}
}
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
@@ -1,7 +1,9 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/FormatMessageTemplate.tt" once="true" #>
/// <summary>
/// Formats a message template and sends an activity event.
/// </summary>
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,18 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -98,675 +82,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
@@ -876,46 +191,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,9 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateValueExpressionTemplate.tt" once="true" #>
/// <summary>
/// Assigns an evaluated expression, other variable, or literal value to one or more variables.
/// </summary>
@@ -10,10 +10,7 @@
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,17 +24,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -87,785 +73,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
{
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
@@ -1,7 +1,10 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/FormatMessageTemplate.tt" once="true" #>
/// <summary>
/// Assigns an evaluated message template to the "<#= this.Model.Variable #>" variable.
/// </summary>
@@ -9,11 +9,7 @@
// ------------------------------------------------------------------------------
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
{
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using System.Collections.Generic;
using System;
/// <summary>
@@ -27,18 +23,6 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
/// </summary>
public override string TransformText()
{
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
this.Write("\n");
@@ -89,675 +73,6 @@ this.Write("\n ");
}
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
{
if (expression is null)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatBoolValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<bool>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<bool>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateEnumExpression<TWrapper, TValue>(
EnumExpression<TWrapper> expression,
string targetVariable,
IDictionary<TWrapper, string> resultMap,
string defaultValue = null,
bool qualifyResult = false,
bool isNullable = false)
where TWrapper : EnumWrapper
{
string resultType = $"{GetTypeAlias<TValue>()}{(isNullable ? "?" : "")}";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(defaultValue)));
this.Write(";");
}
else if (expression.IsLiteral)
{
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
if (qualifyResult)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TValue>()));
this.Write(".");
this.Write(this.ToStringHelper.ToStringWithCulture(resultValue));
this.Write(";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatValue<TValue>(resultValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultType));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "int?" : "int";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "0"));
this.Write(";");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<int>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
{
string typeName = GetTypeAlias<TElement>();
if (expression is null)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(GetTypeAlias<TElement>()));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write("> = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n IList<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateListAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
{
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = null;");
}
else if (expression.IsLiteral)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" =\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatDataValue(expression.LiteralValue)));
this.Write(";");
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write("? ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateExpressionAsync<");
this.Write(this.ToStringHelper.ToStringWithCulture(resultTypeName));
this.Write(">(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
{
string typeName = isNullable ? "string?" : "string";
if (expression is null)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(isNullable ? "null" : "string.Empty"));
this.Write(";");
}
else if (expression.IsLiteral)
{
if (expression.LiteralValue.Contains("\n"))
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = \n \"\"\"\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.LiteralValue));
this.Write("\n \"\"\";");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = ");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.LiteralValue)));
this.Write(";");
}
}
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.ReadStateAsync<string>(key: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.VariableName));
this.Write("\", scopeName: \"");
this.Write(this.ToStringHelper.ToStringWithCulture(expression.VariableReference.NamespaceAlias));
this.Write("\").ConfigureAwait(false);");
}
else if (expression.IsVariableReference)
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.VariableReference.ToString())));
this.Write(").ConfigureAwait(false);");
}
else
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(typeName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(targetVariable));
this.Write(" = await context.EvaluateValueAsync<string>(");
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(expression.ExpressionText)));
this.Write(").ConfigureAwait(false);");
}
}
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
EvaluateValueExpression<object>(expression, targetVariable);
@@ -867,46 +182,5 @@ this.Write(").ConfigureAwait(false);");
}
}
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
{
if (templateLine is not null)
{
this.Write("\n string ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" =\n await context.FormatTemplateAsync(\n \"\"\"");
FormatMessageTemplate(templateLine);
this.Write("\n \"\"\");");
}
else
{
this.Write("\n string? ");
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
this.Write(" = null;");
}
}
void FormatMessageTemplate(TemplateLine line)
{
foreach (string text in line.ToTemplateString().ByLine())
{
this.Write("\n ");
this.Write(this.ToStringHelper.ToStringWithCulture(text));
}
}
}
}
@@ -1,7 +1,9 @@
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ include file="Snippets/Index.tt" once="true" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ include file="Snippets/AssignVariableTemplate.tt" once="true" #>
<#@ include file="Snippets/EvaluateValueExpressionTemplate.tt" once="true" #>
/// <summary>
/// Assigns an evaluated expression, other variable, or literal value to the "<#= this.Model.Variable #>" variable.
/// </summary>
@@ -1,14 +0,0 @@
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.ObjectModel" #>
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
<#@ import namespace="Microsoft.Extensions.AI" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ include file="AssignVariableTemplate.tt" once="true" #>
<#@ include file="EvaluateBoolExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateEnumExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateIntExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateListExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateRecordExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateStringExpressionTemplate.tt" once="true" #>
<#@ include file="EvaluateValueExpressionTemplate.tt" once="true" #>
<#@ include file="FormatMessageTemplate.tt" once="true" #>
@@ -17,7 +17,9 @@ internal sealed class AddConversationMessageExecutor(AddConversationMessage mode
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
Throw.IfNull(this.Model.Message);
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
bool isWorkflowConversation = context.IsWorkflowConversation(conversationId, out string? _);
@@ -26,7 +28,7 @@ internal sealed class AddConversationMessageExecutor(AddConversationMessage mode
// Capture the created message, which includes the assigned ID.
newMessage = await agentProvider.CreateMessageAsync(conversationId, newMessage, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(this.Model.Message?.Path, newMessage.ToRecord(), context).ConfigureAwait(false);
await this.AssignAsync(this.Model.Message.Path, newMessage.ToRecord(), context).ConfigureAwait(false);
if (isWorkflowConversation)
{
@@ -23,7 +23,7 @@ internal sealed class ClearAllVariablesExecutor(ClearAllVariables model, Workflo
VariablesToClear.ConversationScopedVariables => WorkflowFormulaState.DefaultScopeName,
VariablesToClear.ConversationHistory => null,
VariablesToClear.UserScopedVariables => null,
_ => null
_ => null,
};
if (scope is not null)
@@ -7,6 +7,7 @@ using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.PowerFx.Types;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
@@ -15,8 +16,10 @@ internal sealed class CreateConversationExecutor(CreateConversation model, Workf
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false);
await this.AssignAsync(this.Model.ConversationId?.Path, FormulaValue.New(conversationId), context).ConfigureAwait(false);
await this.AssignAsync(this.Model.ConversationId.Path, FormulaValue.New(conversationId), context).ConfigureAwait(false);
await context.QueueConversationUpdateAsync(conversationId, cancellationToken).ConfigureAwait(false);
return default;
@@ -18,12 +18,12 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
PropertyPath variablePath = Throw.IfNull(this.Model.ItemsVariable?.Path, $"{nameof(this.Model)}.{nameof(this.Model.ItemsVariable)}");
Throw.IfNull(this.Model.ItemsVariable, $"{nameof(this.Model)}.{nameof(this.Model.ItemsVariable)}");
FormulaValue table = context.ReadState(variablePath);
FormulaValue table = context.ReadState(this.Model.ItemsVariable);
if (table is not TableValue tableValue)
{
throw this.Exception($"Require '{variablePath}' to be a table, not: '{table.GetType().Name}'.");
throw this.Exception($"Require '{this.Model.ItemsVariable.Path}' to be a table, not: '{table.GetType().Name}'.");
}
EditTableOperation? changeType = this.Model.ChangeType;
@@ -33,12 +33,12 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
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);
await this.AssignAsync(this.Model.ItemsVariable, newRecord, context).ConfigureAwait(false);
}
else if (changeType is ClearItemsOperation)
{
await tableValue.ClearAsync(cancellationToken).ConfigureAwait(false);
await this.AssignAsync(variablePath, FormulaValue.NewBlank(), context).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, FormulaValue.NewBlank(), context).ConfigureAwait(false);
}
else if (changeType is RemoveItemOperation removeItemOperation)
{
@@ -46,8 +46,8 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
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);
await tableValue.RemoveAsync(removeItemTable.Rows.Select(row => row.Value), all: true, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, FormulaValue.NewBlank(), context).ConfigureAwait(false);
}
}
else if (changeType is TakeLastItemOperation)
@@ -56,7 +56,7 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
if (lastRow is not null)
{
await tableValue.RemoveAsync([lastRow], all: true, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(variablePath, lastRow, context).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, lastRow, context).ConfigureAwait(false);
}
}
else if (changeType is TakeFirstItemOperation)
@@ -65,7 +65,7 @@ internal sealed class EditTableV2Executor(EditTableV2 model, WorkflowFormulaStat
if (firstRow is not null)
{
await tableValue.RemoveAsync([firstRow], all: true, cancellationToken).ConfigureAwait(false);
await this.AssignAsync(variablePath, firstRow, context).ConfigureAwait(false);
await this.AssignAsync(this.Model.ItemsVariable, firstRow, context).ConfigureAwait(false);
}
}
@@ -19,24 +19,18 @@ internal sealed class ParseValueExecutor(ParseValue model, WorkflowFormulaState
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
PropertyPath variablePath = Throw.IfNull(this.Model.Variable?.Path, $"{nameof(this.Model)}.{nameof(model.Variable)}");
Throw.IfNull(this.Model.ValueType, $"{nameof(this.Model)}.{nameof(model.ValueType)}");
Throw.IfNull(this.Model.Variable, $"{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 parsedValue;
if (this.Model.ValueType is not null)
{
VariableType targetType = new(this.Model.ValueType);
object? parsedResult = expressionResult.Value.ToObject().ConvertType(targetType);
parsedValue = parsedResult.ToFormula();
}
else
{
parsedValue = expressionResult.Value.ToFormula();
}
VariableType targetType = new(this.Model.ValueType);
object? parsedResult = expressionResult.Value.ToObject().ConvertType(targetType);
parsedValue = parsedResult.ToFormula();
await this.AssignAsync(variablePath, parsedValue, context).ConfigureAwait(false);
await this.AssignAsync(this.Model.Variable.Path, parsedValue, context).ConfigureAwait(false);
return default;
}
@@ -17,6 +17,7 @@ internal sealed class ResetVariableExecutor(ResetVariable model, WorkflowFormula
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
Throw.IfNull(this.Model.Variable, $"{nameof(this.Model)}.{nameof(model.Variable)}");
await context.QueueStateResetAsync(this.Model.Variable, cancellationToken).ConfigureAwait(false);
Debug.WriteLine(
$"""
@@ -16,13 +16,15 @@ internal sealed class RetrieveConversationMessageExecutor(RetrieveConversationMe
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
Throw.IfNull(this.Model.Message);
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);
await this.AssignAsync(this.Model.Message.Path, message.ToRecord(), context).ConfigureAwait(false);
return default;
}
@@ -18,11 +18,13 @@ internal sealed class RetrieveConversationMessagesExecutor(RetrieveConversationM
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
Throw.IfNull(this.Model.Messages);
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
List<ChatMessage> messages = [];
await foreach (var m in agentProvider.GetMessagesAsync(
await foreach (ChatMessage message in agentProvider.GetMessagesAsync(
conversationId,
limit: this.GetLimit(),
after: this.GetMessage(this.Model.MessageAfter),
@@ -30,21 +32,16 @@ internal sealed class RetrieveConversationMessagesExecutor(RetrieveConversationM
newestFirst: this.IsDescending(),
cancellationToken).ConfigureAwait(false))
{
messages.Add(m);
messages.Add(message);
}
await this.AssignAsync(this.Model.Messages?.Path, messages.ToTable(), context).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));
}
@@ -61,11 +58,6 @@ internal sealed class RetrieveConversationMessagesExecutor(RetrieveConversationM
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;
@@ -7,6 +7,7 @@ using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.PowerFx.Types;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
@@ -15,16 +16,12 @@ internal sealed class SetTextVariableExecutor(SetTextVariable model, WorkflowFor
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
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));
Throw.IfNull(this.Model.Variable);
Throw.IfNull(this.Model.Value);
await this.AssignAsync(this.Model.Variable?.Path, expressionResult, context).ConfigureAwait(false);
}
FormulaValue expressionResult = FormulaValue.New(this.Engine.Format(this.Model.Value));
await this.AssignAsync(this.Model.Variable.Path, expressionResult, context).ConfigureAwait(false);
return default;
}
@@ -7,7 +7,7 @@ using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.Agents.ObjectModel.Abstractions;
using Microsoft.PowerFx.Types;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
@@ -16,16 +16,12 @@ internal sealed class SetVariableExecutor(SetVariable model, WorkflowFormulaStat
{
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
{
if (this.Model.Value is null)
{
await this.AssignAsync(this.Model.Variable?.Path, FormulaValue.NewBlank(), context).ConfigureAwait(false);
}
else
{
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Value);
Throw.IfNull(this.Model.Variable);
Throw.IfNull(this.Model.Value);
await this.AssignAsync(this.Model.Variable?.Path, expressionResult.Value.ToFormula(), context).ConfigureAwait(false);
}
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Value);
await this.AssignAsync(this.Model.Variable.Path, expressionResult.Value.ToFormula(), context).ConfigureAwait(false);
return default;
}
@@ -21,42 +21,51 @@ public sealed class MediaInputTest(ITestOutputHelper output) : IntegrationTest(o
{
private const string WorkflowWithConversationFileName = "MediaInputConversation.yaml";
private const string WorkflowWithAutoSendFileName = "MediaInputAutoSend.yaml";
private const string PdfReference = "https://sample-files.com/downloads/documents/pdf/basic-text.pdf";
private const string ImageReference = "https://sample-files.com/downloads/images/jpg/web_optimized_1200x800_97kb.jpg";
private const string PdfReference = "https://sample-files.com/downloads/documents/pdf/basic-text.pdf";
[Theory]
[InlineData(ImageReference, "image/jpeg", true, Skip = "Failing due to agent service bug.")]
[InlineData(ImageReference, "image/jpeg", false, Skip = "Failing due to agent service bug.")]
[InlineData(ImageReference, "image/jpeg", true)]
[InlineData(ImageReference, "image/jpeg", false)]
public async Task ValidateFileUrlAsync(string fileSource, string mediaType, bool useConversation)
{
this.Output.WriteLine($"File: {ImageReference}");
// Arrange
this.Output.WriteLine($"File: {fileSource}");
// Act & Assert
await this.ValidateFileAsync(new UriContent(fileSource, mediaType), useConversation);
}
[Theory]
[InlineData(ImageReference, "image/jpeg", true)]
[InlineData(ImageReference, "image/jpeg", false, Skip = "Failing due to agent service bug.")]
[InlineData(ImageReference, "image/jpeg", false)]
[InlineData(PdfReference, "application/pdf", true)]
[InlineData(PdfReference, "application/pdf", false)]
public async Task ValidateFileDataAsync(string fileSource, string mediaType, bool useConversation)
{
// Arrange
byte[] fileData = await DownloadFileAsync(fileSource);
string encodedData = Convert.ToBase64String(fileData);
string fileUrl = $"data:{mediaType};base64,{encodedData}";
this.Output.WriteLine($"Content: {fileUrl.Substring(0, 112)}...");
this.Output.WriteLine($"Content: {fileUrl.Substring(0, Math.Min(112, fileUrl.Length))}...");
// Act & Assert
await this.ValidateFileAsync(new DataContent(fileUrl), useConversation);
}
[Theory]
[InlineData(PdfReference, "doc.pdf", true, Skip = "Failing due to agent service bug.")]
[InlineData(PdfReference, "doc.pdf", false, Skip = "Failing due to agent service bug.")]
[InlineData(PdfReference, "doc.pdf", true)]
[InlineData(PdfReference, "doc.pdf", false)]
public async Task ValidateFileUploadAsync(string fileSource, string documentName, bool useConversation)
{
// Arrange
byte[] fileData = await DownloadFileAsync(fileSource);
AIProjectClient client = new(this.TestEndpoint, new AzureCliCredential());
using MemoryStream contentStream = new(fileData);
OpenAIFileClient fileClient = client.GetProjectOpenAIClient().GetOpenAIFileClient();
OpenAIFile fileInfo = await fileClient.UploadFileAsync(contentStream, documentName, FileUploadPurpose.Assistants);
// Act & Assert
try
{
this.Output.WriteLine($"File: {fileInfo.Id}");
@@ -77,6 +86,7 @@ public sealed class MediaInputTest(ITestOutputHelper output) : IntegrationTest(o
private async Task ValidateFileAsync(AIContent fileContent, bool useConversation)
{
// Act
AgentProvider agentProvider = AgentProvider.Create(this.Configuration, AgentProvider.Names.Vision);
await agentProvider.CreateAgentsAsync().ConfigureAwait(false);
@@ -93,6 +103,8 @@ public sealed class MediaInputTest(ITestOutputHelper output) : IntegrationTest(o
WorkflowHarness harness = new(workflow, runId: Path.GetFileNameWithoutExtension(workflowFileName));
WorkflowEvents workflowEvents = await harness.RunWorkflowAsync(inputMessage).ConfigureAwait(false);
// Assert
Assert.Equal(useConversation ? 1 : 2, workflowEvents.ConversationEvents.Count);
this.Output.WriteLine("CONVERSATION: " + workflowEvents.ConversationEvents[0].ConversationId);
AgentResponseEvent agentResponseEvent = Assert.Single(workflowEvents.AgentResponseEvents);
@@ -10,7 +10,6 @@
"conversation_count": 1,
"min_action_count": 1,
"min_response_count": 1,
"min_message_count": 2,
"actions": {
"start": [
"invoke_poem"
@@ -10,7 +10,6 @@
"conversation_count": 1,
"min_action_count": 3,
"min_response_count": 3,
"min_message_count": 6,
"actions": {
"start": [
"invoke_analyst",
@@ -17,7 +17,7 @@ internal sealed class MockAgentProvider : Mock<WorkflowAgentProvider>
{
public IList<string> ExistingConversationIds { get; } = [];
public List<ChatMessage>? TestMessages { get; set; }
public List<ChatMessage> TestMessages { get; set; } = [];
public MockAgentProvider()
{
@@ -45,7 +45,7 @@ internal sealed class MockAgentProvider : Mock<WorkflowAgentProvider>
It.IsAny<string>(),
It.IsAny<ChatMessage>(),
It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(testMessages.First()));
.Returns<string, ChatMessage, CancellationToken>((conversationId, message, cancellationToken) => Task.FromResult(this.CaptureChatMessage(message)));
}
private string CreateConversationId()
@@ -56,6 +56,13 @@ internal sealed class MockAgentProvider : Mock<WorkflowAgentProvider>
return newConversationId;
}
private ChatMessage CaptureChatMessage(ChatMessage message)
{
this.TestMessages.Add(message);
return message;
}
private List<ChatMessage> CreateMessages()
{
// Create test messages
@@ -1,11 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
using Microsoft.Agents.ObjectModel;
using Microsoft.Extensions.AI;
using Microsoft.PowerFx.Types;
using Xunit.Abstractions;
namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel;
@@ -28,20 +31,64 @@ public sealed class AddConversationMessageExecutorTest(ITestOutputHelper output)
messageText: $"Hello from {role}");
}
[Theory]
[InlineData(AgentMessageRole.User)]
[InlineData(AgentMessageRole.Agent)]
public async Task AddMessageToWorkflowAsync(AgentMessageRole role)
{
// Arrange
this.State.Set(SystemScope.Names.ConversationId, FormulaValue.New("WorkflowConversationId"), VariableScopeNames.System);
// Act & Assert
await this.ExecuteTestAsync(
displayName: nameof(AddMessageToWorkflowAsync),
variableName: "TestMessage",
role: AgentMessageRoleWrapper.Get(role),
conversationId: "WorkflowConversationId",
messageText: $"Hello from {role}");
}
[Theory]
[InlineData(AgentMessageRole.User)]
[InlineData(AgentMessageRole.Agent)]
public async Task AddMessageWithMetadataAsync(AgentMessageRole role)
{
// Arrange
Dictionary<string, string> metadataValues =
new()
{
["Key1"] = "Value1",
["Key2"] = "Value2",
};
RecordDataValue metadataRecord = metadataValues.ToRecordValue();
// Act & Assert
await this.ExecuteTestAsync(
displayName: nameof(AddMessageWithMetadataAsync),
variableName: "TestMessage",
role: AgentMessageRoleWrapper.Get(role),
messageText: $"Hello from {role}",
metadata: metadataRecord);
}
private async Task ExecuteTestAsync(
string displayName,
string variableName,
AgentMessageRoleWrapper role,
string messageText)
string messageText,
string? conversationId = null,
RecordDataValue? metadata = null)
{
// Arrange
MockAgentProvider mockAgentProvider = new();
AddConversationMessage model = this.CreateModel(
this.FormatDisplayName(displayName),
FormatVariablePath(variableName),
"TestConversationId",
role,
messageText);
AddConversationMessage model =
this.CreateModel(
this.FormatDisplayName(displayName),
FormatVariablePath(variableName),
conversationId ?? "TestConversationId",
role,
messageText,
metadata);
AddConversationMessageExecutor action = new(model, mockAgentProvider.Object, this.State);
@@ -49,10 +96,15 @@ public sealed class AddConversationMessageExecutorTest(ITestOutputHelper output)
await this.ExecuteAsync(action);
// Assert
ChatMessage? testMessage = mockAgentProvider.TestMessages?.FirstOrDefault();
ChatMessage? testMessage = mockAgentProvider.TestMessages?.LastOrDefault();
Assert.NotNull(testMessage);
VerifyModel(model, action);
this.VerifyState(variableName, testMessage.ToRecord());
if (metadata is not null)
{
Assert.NotNull(testMessage.AdditionalProperties);
Assert.NotEmpty(testMessage.AdditionalProperties);
}
}
private AddConversationMessage CreateModel(
@@ -60,8 +112,15 @@ public sealed class AddConversationMessageExecutorTest(ITestOutputHelper output)
string messageVariable,
string conversationId,
AgentMessageRoleWrapper role,
string messageText)
string messageText,
RecordDataValue? metadata)
{
ObjectExpression<RecordDataValue>.Builder? metadataExpression = null;
if (metadata is not null)
{
metadataExpression = ObjectExpression<RecordDataValue>.Literal(metadata).ToBuilder();
}
AddConversationMessage.Builder actionBuilder =
new()
{
@@ -70,6 +129,7 @@ public sealed class AddConversationMessageExecutorTest(ITestOutputHelper output)
Message = PropertyPath.Create(messageVariable),
ConversationId = StringExpression.Literal(conversationId),
Role = role,
Metadata = metadataExpression,
};
actionBuilder.Content.Add(new AddConversationMessageContent.Builder
@@ -13,47 +13,91 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel;
/// </summary>
public sealed class ClearAllVariablesExecutorTest(ITestOutputHelper output) : WorkflowActionExecutorTest(output)
{
[Fact]
public async Task ClearGlobalScopeAsync()
{
// Arrange
this.State.Set("GlobalVar", FormulaValue.New("Old value"), VariableScopeNames.Global);
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ClearGlobalScopeAsync)),
VariablesToClear.AllGlobalVariables,
"GlobalVar",
VariableScopeNames.Global);
}
[Fact]
public async Task ClearWorkflowScopeAsync()
{
// Arrange
this.State.Set("NoVar", FormulaValue.New("Old value"));
this.State.Set("LocalVar", FormulaValue.New("Old value"));
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ClearWorkflowScopeAsync)),
VariablesToClear.ConversationScopedVariables,
"LocalVar");
}
[Fact]
public async Task ClearUserScopeAsync()
{
// Arrange
this.State.Set("LocalVar", FormulaValue.New("Old value"));
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ClearUserScopeAsync)),
VariablesToClear.UserScopedVariables,
"LocalVar",
expectedValue: FormulaValue.New("Old value"));
}
[Fact]
public async Task ClearWorkflowHistoryAsync()
{
// Arrange
this.State.Set("LocalVar", FormulaValue.New("Old value"));
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ClearWorkflowHistoryAsync)),
VariablesToClear.ConversationHistory,
"LocalVar",
expectedValue: FormulaValue.New("Old value"));
}
private async Task ExecuteTestAsync(
string displayName,
VariablesToClear scope,
string variableName,
string variableScope = VariableScopeNames.Local,
FormulaValue? expectedValue = null)
{
// Arrange
ClearAllVariables model = this.CreateModel(
this.FormatDisplayName(displayName),
scope);
ClearAllVariablesExecutor action = new(model, this.State);
this.State.Bind();
ClearAllVariables model =
this.CreateModel(
this.FormatDisplayName(nameof(ClearWorkflowScopeAsync)),
VariablesToClear.ConversationScopedVariables);
// Act
ClearAllVariablesExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyUndefined("NoVar");
}
[Fact]
public async Task ClearUndefinedScopeAsync()
{
// Arrange
this.State.Set("NoVar", FormulaValue.New("Old value"));
this.State.Bind();
// Arrange
ClearAllVariables model =
this.CreateModel(
this.FormatDisplayName(nameof(ClearUndefinedScopeAsync)),
VariablesToClear.UserScopedVariables);
// Act
ClearAllVariablesExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("NoVar", FormulaValue.New("Old value"));
if (expectedValue is null)
{
this.VerifyUndefined(variableName, variableScope);
}
else
{
this.VerifyState(variableName, variableScope, expectedValue);
}
}
private ClearAllVariables CreateModel(string displayName, VariablesToClear variableTarget)
@@ -0,0 +1,345 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
using Microsoft.PowerFx.Types;
using Xunit.Abstractions;
namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel;
/// <summary>
/// Tests for <see cref="EditTableV2Executor"/>.
/// </summary>
public sealed class EditTableV2ExecutorTest(ITestOutputHelper output) : WorkflowActionExecutorTest(output)
{
[Fact]
public void InvalidModelNullItemsVariable()
{
// Arrange
EditTableV2 model = new EditTableV2.Builder
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(nameof(InvalidModelNullItemsVariable)),
ItemsVariable = null,
ChangeType = new AddItemOperation.Builder
{
Value = new ValueExpression.Builder(ValueExpression.Literal(new StringDataValue("test")))
}.Build()
}.Build();
// Act, Assert
DeclarativeModelException exception = Assert.Throws<DeclarativeModelException>(() => new EditTableV2Executor(model, this.State));
Assert.Contains("required", exception.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public async Task InvalidModelVariableNotTableAsync()
{
// Arrange
this.State.Set("NotATable", FormulaValue.New("I am a string"));
EditTableV2 model = this.CreateModel(
nameof(InvalidModelVariableNotTableAsync),
"NotATable",
new AddItemOperation.Builder
{
Value = new ValueExpression.Builder(ValueExpression.Literal(new StringDataValue("test")))
}.Build());
EditTableV2Executor action = new(model, this.State);
// Act & Assert
await Assert.ThrowsAsync<DeclarativeActionException>(async () => await this.ExecuteAsync(action));
}
[Fact]
public async Task InvalidModelAddItemOperationNullValueAsync()
{
// Arrange
EditTableV2 model = new EditTableV2.Builder
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(nameof(InvalidModelAddItemOperationNullValueAsync)),
ItemsVariable = PropertyPath.Create(FormatVariablePath("TestTable")),
ChangeType = new AddItemOperation.Builder
{
Value = null
}.Build()
}.Build();
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Act, Assert
EditTableV2Executor action = new(model, this.State);
await Assert.ThrowsAsync<DeclarativeActionException>(async () => await this.ExecuteAsync(action));
}
[Fact]
public async Task InvalidModelRemoveItemOperationNullValueAsync()
{
// Arrange
EditTableV2 model = new EditTableV2.Builder
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(nameof(InvalidModelRemoveItemOperationNullValueAsync)),
ItemsVariable = PropertyPath.Create(FormatVariablePath("TestTable")),
ChangeType = new RemoveItemOperation.Builder
{
Value = null
}.Build()
}.Build();
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Act, Assert
EditTableV2Executor action = new(model, this.State);
await Assert.ThrowsAsync<DeclarativeActionException>(async () => await this.ExecuteAsync(action));
}
[Fact]
public async Task RemoveItemOperationNonTableValueAsync()
{
// Arrange
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue record1 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item1")));
TableValue tableValue = FormulaValue.NewTable(recordType, record1);
this.State.Set("TestTable", tableValue);
// Set a string value instead of a table for removal
this.State.Set("RemoveItems", FormulaValue.New("NotATable"));
EditTableV2 model = new EditTableV2.Builder
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(nameof(RemoveItemOperationNonTableValueAsync)),
ItemsVariable = PropertyPath.Create(FormatVariablePath("TestTable")),
ChangeType = new RemoveItemOperation.Builder
{
Value = new ValueExpression.Builder(ValueExpression.Variable(PropertyPath.TopicVariable("RemoveItems")))
}.Build()
}.Build();
// Act
EditTableV2Executor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert: When the remove value is not a table, no removal occurs, so the table should be unchanged
FormulaValue value = this.State.Get("TestTable");
Assert.IsAssignableFrom<TableValue>(value);
TableValue resultTable = (TableValue)value;
Assert.Single(resultTable.Rows);
}
[Fact]
public async Task AddItemOperationWithSingleFieldRecordAsync()
{
// Arrange: Create an empty table with single field
RecordType recordType = RecordType.Empty().Add("Name", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Arrange, Act, Assert
await this.ExecuteTestAsync<RecordValue>(
displayName: nameof(AddItemOperationWithSingleFieldRecordAsync),
variableName: "TestTable",
changeType: this.CreateAddItemOperation(new RecordDataValue.Builder
{
Properties =
{
["Name"] = new StringDataValue("John")
}
}.Build()),
verifyAction: (variableName, recordValue) =>
Assert.Equal("John", recordValue.GetField("Name").ToObject())
);
}
[Fact]
public async Task AddItemOperationWithScalarValueAsync()
{
// Arrange: Create an empty table with single field
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Act & Assert
await this.ExecuteTestAsync<RecordValue>(
displayName: nameof(AddItemOperationWithScalarValueAsync),
variableName: "TestTable",
changeType: this.CreateAddItemOperation(new StringDataValue("TestValue")),
verifyAction: (variableName, recordValue) =>
Assert.Equal("TestValue", recordValue.GetField("Value").ToObject())
);
}
[Fact]
public async Task ClearItemsOperationAsync()
{
// Arrange: Create a table with some items
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue record1 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item1")));
RecordValue record2 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item2")));
TableValue tableValue = FormulaValue.NewTable(recordType, record1, record2);
this.State.Set("TestTable", tableValue);
// Act & Assert
await this.ExecuteTestAsync<BlankValue>(
displayName: nameof(ClearItemsOperationAsync),
variableName: "TestTable",
changeType: new ClearItemsOperation.Builder().Build());
}
[Fact]
public async Task RemoveItemOperationAsync()
{
// Arrange: Create a table with some items
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue record1 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item1")));
RecordValue record2 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item2")));
TableValue tableValue = FormulaValue.NewTable(recordType, record1, record2);
this.State.Set("TestTable", tableValue);
// Act & Assert
await this.ExecuteTestAsync<BlankValue>(
displayName: nameof(RemoveItemOperationAsync),
variableName: "TestTable",
changeType: this.CreateRemoveItemOperation("Item1"));
}
[Fact]
public async Task TakeLastItemOperationWithItemsAsync()
{
// Arrange: Create a table with some items
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue record1 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item1")));
RecordValue record2 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item2")));
RecordValue record3 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item3")));
TableValue tableValue = FormulaValue.NewTable(recordType, record1, record2, record3);
this.State.Set("TestTable", tableValue);
// Arrange, Act, Assert
await this.ExecuteTestAsync<RecordValue>(
displayName: nameof(TakeLastItemOperationWithItemsAsync),
variableName: "TestTable",
changeType: new TakeLastItemOperation.Builder().Build(),
verifyAction: (variableName, recordValue) =>
Assert.Equal("Item3", recordValue.GetField("Value").ToObject())
);
}
[Fact]
public async Task TakeLastItemOperationEmptyTableAsync()
{
// Arrange: Create an empty table
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Arrange, Act, Assert
await this.ExecuteTestAsync<TableValue>(
displayName: nameof(TakeLastItemOperationEmptyTableAsync),
variableName: "TestTable",
changeType: new TakeLastItemOperation.Builder().Build());
}
[Fact]
public async Task TakeFirstItemOperationWithItemsAsync()
{
// Arrange: Create a table with some items
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue record1 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item1")));
RecordValue record2 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item2")));
RecordValue record3 = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New("Item3")));
TableValue tableValue = FormulaValue.NewTable(recordType, record1, record2, record3);
this.State.Set("TestTable", tableValue);
// Act & Assert
await this.ExecuteTestAsync<RecordValue>(
displayName: nameof(TakeFirstItemOperationWithItemsAsync),
variableName: "TestTable",
changeType: new TakeFirstItemOperation.Builder().Build(),
verifyAction: (variableName, recordValue) =>
Assert.Equal("Item1", recordValue.GetField("Value").ToObject())
);
}
[Fact]
public async Task TakeFirstItemOperationEmptyTableAsync()
{
// Arrange: Create an empty table
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
TableValue tableValue = FormulaValue.NewTable(recordType);
this.State.Set("TestTable", tableValue);
// Act & Assert
await this.ExecuteTestAsync<TableValue>(
displayName: nameof(TakeFirstItemOperationEmptyTableAsync),
variableName: "TestTable",
changeType: new TakeFirstItemOperation.Builder().Build());
}
private async Task ExecuteTestAsync<TValue>(
string displayName,
string variableName,
EditTableOperation changeType,
Action<string, TValue>? verifyAction = null) where TValue : FormulaValue
{
// Arrange
EditTableV2 model = this.CreateModel(displayName, variableName, changeType);
EditTableV2Executor action = new(model, this.State);
// Act
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
FormulaValue value = this.State.Get(variableName);
TValue typedValue = Assert.IsAssignableFrom<TValue>(value);
verifyAction?.Invoke(variableName, typedValue);
}
private EditTableV2 CreateModel(string displayName, string variableName, EditTableOperation changeType)
{
EditTableV2.Builder actionBuilder = new()
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(displayName),
ItemsVariable = PropertyPath.Create(FormatVariablePath(variableName)),
ChangeType = changeType
};
return AssignParent<EditTableV2>(actionBuilder);
}
private AddItemOperation CreateAddItemOperation(DataValue value)
{
return new AddItemOperation.Builder
{
Value = new ValueExpression.Builder(ValueExpression.Literal(value))
}.Build();
}
private RemoveItemOperation CreateRemoveItemOperation(string itemValue)
{
// Create a table with the item to remove
RecordType recordType = RecordType.Empty().Add("Value", FormulaType.String);
RecordValue recordToRemove = FormulaValue.NewRecordFromFields(recordType, new NamedValue("Value", FormulaValue.New(itemValue)));
TableValue tableToRemove = FormulaValue.NewTable(recordType, recordToRemove);
// Store in state for expression evaluation
this.State.Set("RemoveItems", tableToRemove);
this.State.Bind();
return new RemoveItemOperation.Builder
{
Value = new ValueExpression.Builder(ValueExpression.Variable(PropertyPath.TopicVariable("RemoveItems")))
}.Build();
}
}
@@ -25,95 +25,71 @@ public sealed class ParseValueExecutorTest(ITestOutputHelper output) : WorkflowA
{"key1", new PropertyInfo.Builder() { Type = DataType.String } },
}
};
ParseValue model =
this.CreateModel(
this.FormatDisplayName(nameof(ParseRecordAsync)),
recordBuilder,
@"{ ""key1"": ""val1"" }");
// Act
ParseValueExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("Target", FormulaValue.NewRecordFromFields(new NamedValue("key1", FormulaValue.New("val1"))));
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ParseRecordAsync)),
recordBuilder,
@"{ ""key1"": ""val1"" }",
FormulaValue.NewRecordFromFields(new NamedValue("key1", FormulaValue.New("val1"))));
}
[Fact]
public async Task ParseTableAsync()
{
// Arrange
RecordDataType.Builder recordBuilder =
new()
{
Properties =
{
{"key1", new PropertyInfo.Builder() { Type = DataType.String } },
}
};
ParseValue model =
this.CreateModel(
this.FormatDisplayName(nameof(ParseTableAsync)),
DataType.EmptyTable,
@"[""apple"",""banana"",""cat""]");
// Act
ParseValueExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("Target", FormulaValue.NewSingleColumnTable(FormulaValue.New("apple"), FormulaValue.New("banana"), FormulaValue.New("cat")));
// Arrange, Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ParseTableAsync)),
DataType.EmptyTable,
@"[""apple"",""banana"",""cat""]",
FormulaValue.NewSingleColumnTable(FormulaValue.New("apple"), FormulaValue.New("banana"), FormulaValue.New("cat")));
}
[Fact]
public async Task ParseBooleanAsync()
{
// Arrange
ParseValue model =
this.CreateModel(
this.FormatDisplayName(nameof(ParseTableAsync)),
new BooleanDataType.Builder(),
"True");
// Act
ParseValueExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("Target", FormulaValue.New(true));
// Arrange, Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ParseBooleanAsync)),
new BooleanDataType.Builder(),
"True",
FormulaValue.New(true));
}
[Fact]
public async Task ParseNumberAsync()
{
// Arrange
ParseValue model =
this.CreateModel(
this.FormatDisplayName(nameof(ParseNumberAsync)),
new NumberDataType.Builder(),
"42");
// Act
ParseValueExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("Target", FormulaValue.New(42));
// Arrange, Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ParseNumberAsync)),
new NumberDataType.Builder(),
"42",
FormulaValue.New(42));
}
[Fact]
public async Task ParseStringAsync()
{
// Arrange
// Arrange, Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(ParseStringAsync)),
new StringDataType.Builder(),
"Hello, World!",
FormulaValue.New("Hello, World!"));
}
private async Task ExecuteTestAsync(
string displayName,
DataType.Builder dataBuilder,
string sourceText,
FormulaValue expectedValue)
{
ParseValue model =
this.CreateModel(
this.FormatDisplayName(nameof(ParseStringAsync)),
new StringDataType.Builder(),
"Hello, World!");
displayName,
"Target",
dataBuilder,
sourceText);
// Act
ParseValueExecutor action = new(model, this.State);
@@ -121,10 +97,14 @@ public sealed class ParseValueExecutorTest(ITestOutputHelper output) : WorkflowA
// Assert
VerifyModel(model, action);
this.VerifyState("Target", FormulaValue.New("Hello, World!"));
this.VerifyState("Target", expectedValue);
}
private ParseValue CreateModel(string displayName, DataType.Builder typeBuilder, string sourceText)
private ParseValue CreateModel(
string displayName,
string variableName,
DataType.Builder typeBuilder,
string sourceText)
{
ParseValue.Builder actionBuilder =
new()
@@ -132,7 +112,7 @@ public sealed class ParseValueExecutorTest(ITestOutputHelper output) : WorkflowA
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(displayName),
ValueType = typeBuilder,
Variable = PropertyPath.TopicVariable("Target"),
Variable = PropertyPath.TopicVariable(variableName),
Value = new ValueExpression.Builder(ValueExpression.Literal(StringDataValue.Create(sourceText))),
};
@@ -63,7 +63,7 @@ public sealed class ResetVariableExecutorTest(ITestOutputHelper output) : Workfl
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(displayName),
Variable = InitializablePropertyPath.Create(variablePath),
Variable = PropertyPath.Create(variablePath),
};
return AssignParent<ResetVariable>(actionBuilder);
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
using Microsoft.Agents.ObjectModel;
@@ -32,7 +33,6 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
// Arrange
this.State.Set("SourceNumber", FormulaValue.New(10));
this.State.Set("SourceText", FormulaValue.New("Hello"));
this.State.Bind();
// Act, Assert
await this.ExecuteTestAsync(
@@ -50,7 +50,6 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
// Arrange
this.State.Set("Source1", FormulaValue.New(123));
this.State.Set("Source2", FormulaValue.New("Reference"));
this.State.Bind();
// Act, Assert
await this.ExecuteTestAsync(
@@ -74,6 +73,19 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
]);
}
[Fact]
public async Task SetMultipleVariablesWithNullVariableAsync()
{
// Arrange, Act, Assert
await this.ExecuteTestAsync(
displayName: nameof(SetMultipleVariablesWithNullVariableAsync),
assignments: [
new AssignmentCase("NullVar1", null, FormulaValue.NewBlank()),
new AssignmentCase(null, new StringDataValue("NotNull"), FormulaValue.New("NotNull")),
new AssignmentCase("NullVar2", null, FormulaValue.NewBlank())
]);
}
[Fact]
public async Task SetMultipleVariablesUpdateExistingAsync()
{
@@ -116,9 +128,9 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
// Assert
VerifyModel(model, action);
foreach (AssignmentCase assignment in assignments)
foreach (AssignmentCase assignment in assignments.Where(a => a.VariableName != null))
{
this.VerifyState(assignment.VariableName, assignment.ExpectedValue);
this.VerifyState(assignment.VariableName!, assignment.ExpectedValue);
}
}
@@ -140,9 +152,15 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
_ => throw new System.ArgumentException($"Unsupported value type: {assignment.ValueExpression?.GetType().Name}")
};
InitializablePropertyPath? variablePath = null;
if (assignment.VariableName != null)
{
variablePath = PropertyPath.Create(FormatVariablePath(assignment.VariableName));
}
actionBuilder.Assignments.Add(new VariableAssignment.Builder()
{
Variable = PropertyPath.Create(FormatVariablePath(assignment.VariableName)),
Variable = variablePath,
Value = valueExpressionBuilder,
});
}
@@ -150,5 +168,5 @@ public sealed class SetMultipleVariablesExecutorTest(ITestOutputHelper output) :
return AssignParent<SetMultipleVariables>(actionBuilder);
}
private sealed record AssignmentCase(string VariableName, object? ValueExpression, FormulaValue ExpectedValue);
private sealed record AssignmentCase(string? VariableName, object? ValueExpression, FormulaValue ExpectedValue);
}
@@ -16,20 +16,11 @@ public sealed class SetTextVariableExecutorTest(ITestOutputHelper output) : Work
[Fact]
public async Task SetLiteralValueAsync()
{
// Arrange
SetTextVariable model =
this.CreateModel(
// Arrange, Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(SetLiteralValueAsync)),
FormatVariablePath("TextVar"),
"Text variable value");
// Act
SetTextVariableExecutor action = new(model, this.State);
await this.ExecuteAsync(action);
// Assert
VerifyModel(model, action);
this.VerifyState("TextVar", FormulaValue.New("Text variable value"));
"TextVar",
"New value");
}
[Fact]
@@ -38,11 +29,24 @@ public sealed class SetTextVariableExecutorTest(ITestOutputHelper output) : Work
// Arrange
this.State.Set("TextVar", FormulaValue.New("Old value"));
// Act & Assert
await this.ExecuteTestAsync(
this.FormatDisplayName(nameof(UpdateExistingValueAsync)),
"TextVar",
"New value");
}
private async Task ExecuteTestAsync(
string displayName,
string variableName,
string textValue)
{
// Arrange
SetTextVariable model =
this.CreateModel(
this.FormatDisplayName(nameof(UpdateExistingValueAsync)),
FormatVariablePath("TextVar"),
"New value");
displayName,
variableName,
textValue);
// Act
SetTextVariableExecutor action = new(model, this.State);
@@ -50,7 +54,7 @@ public sealed class SetTextVariableExecutorTest(ITestOutputHelper output) : Work
// Assert
VerifyModel(model, action);
this.VerifyState("TextVar", FormulaValue.New("New value"));
this.VerifyState(variableName, FormulaValue.New(textValue));
}
private SetTextVariable CreateModel(string displayName, string variablePath, string textValue)
@@ -60,7 +64,7 @@ public sealed class SetTextVariableExecutorTest(ITestOutputHelper output) : Work
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(displayName),
Variable = InitializablePropertyPath.Create(variablePath),
Variable = PropertyPath.Create(FormatVariablePath(variablePath)),
Value = TemplateLine.Parse(textValue),
};
@@ -92,7 +92,6 @@ public sealed class SetVariableExecutorTest(ITestOutputHelper output) : Workflow
{
// Arrange
this.State.Set("Source", FormulaValue.New(true));
this.State.Bind();
ValueExpression.Builder expressionBuilder = new(ValueExpression.Variable(PropertyPath.TopicVariable("Source")));
@@ -109,7 +108,6 @@ public sealed class SetVariableExecutorTest(ITestOutputHelper output) : Workflow
{
// Arrange
this.State.Set("Source", FormulaValue.New(321));
this.State.Bind();
ValueExpression.Builder expressionBuilder = new(ValueExpression.Variable(PropertyPath.TopicVariable("Source")));
@@ -126,7 +124,6 @@ public sealed class SetVariableExecutorTest(ITestOutputHelper output) : Workflow
{
// Arrange
this.State.Set("Source", FormulaValue.New("Test"));
this.State.Bind();
ValueExpression.Builder expressionBuilder = new(ValueExpression.Variable(PropertyPath.TopicVariable("Source")));
@@ -196,7 +193,7 @@ public sealed class SetVariableExecutorTest(ITestOutputHelper output) : Workflow
{
Id = this.CreateActionId(),
DisplayName = this.FormatDisplayName(displayName),
Variable = InitializablePropertyPath.Create(variablePath),
Variable = PropertyPath.Create(variablePath),
Value = valueExpression,
};
@@ -27,6 +27,8 @@ public abstract class WorkflowActionExecutorTest(ITestOutputHelper output) : Wor
internal async Task<WorkflowEvent[]> ExecuteAsync(DeclarativeActionExecutor executor)
{
this.State.Bind();
TestWorkflowExecutor workflowExecutor = new();
WorkflowBuilder workflowBuilder = new(workflowExecutor);
workflowBuilder.AddEdge(workflowExecutor, executor);
+3 -3
View File
@@ -69,7 +69,7 @@ def equal(arg1: str, arg2: str) -> bool:
```python
# Core
from agent_framework import ChatAgent, ChatMessage, tool
from agent_framework import ChatAgent, Message, tool
# Components
from agent_framework.observability import enable_instrumentation
@@ -84,10 +84,10 @@ from agent_framework.azure import AzureOpenAIChatClient
Define `__all__` in each module. Avoid `from module import *` in `__init__.py` files:
```python
__all__ = ["ChatAgent", "ChatMessage", "ChatResponse"]
__all__ = ["ChatAgent", "Message", "ChatResponse"]
from ._agents import ChatAgent
from ._types import ChatMessage, ChatResponse
from ._types import Message, ChatResponse
```
## Performance Guidelines
+55 -3
View File
@@ -7,6 +7,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [1.0.0b260210] - 2026-02-10
### Added
- **agent-framework-core**: Add long-running agents and background responses support with `ContinuationToken` TypedDict, `background` option in `OpenAIResponsesOptions`, and continuation token propagation through response types ([#3808](https://github.com/microsoft/agent-framework/pull/3808))
- **agent-framework-core**: Add streaming support for code interpreter deltas ([#3775](https://github.com/microsoft/agent-framework/pull/3775))
- **agent-framework-core**: Add explicit input, output, and workflow_output parameters to `@handler`, `@executor` and `request_info` ([#3472](https://github.com/microsoft/agent-framework/pull/3472))
- **agent-framework-core**: Add explicit schema handling to `@tool` decorator ([#3734](https://github.com/microsoft/agent-framework/pull/3734))
- **agent-framework-core**: New session and context provider types ([#3763](https://github.com/microsoft/agent-framework/pull/3763))
- **agent-framework-purview**: Add tests to Purview package ([#3513](https://github.com/microsoft/agent-framework/pull/3513))
### Changed
- **agent-framework-core**: [BREAKING] Renamed core types for simpler API: `ChatAgent``Agent`, `RawChatAgent``RawAgent`, `ChatMessage``Message`, `ChatClientProtocol``SupportsChatGetResponse` ([#3747](https://github.com/microsoft/agent-framework/pull/3747))
- **agent-framework-core**: [BREAKING] Moved to a single `get_response` and `run` API ([#3379](https://github.com/microsoft/agent-framework/pull/3379))
- **agent-framework-core**: [BREAKING] Merge `send_responses` into `run` method ([#3720](https://github.com/microsoft/agent-framework/pull/3720))
- **agent-framework-core**: [BREAKING] Renamed `AgentRunContext` to `AgentContext` ([#3714](https://github.com/microsoft/agent-framework/pull/3714))
- **agent-framework-core**: [BREAKING] Renamed `AgentProtocol` to `SupportsAgentRun` ([#3717](https://github.com/microsoft/agent-framework/pull/3717))
- **agent-framework-core**: [BREAKING] Renamed next middleware parameter to `call_next` ([#3735](https://github.com/microsoft/agent-framework/pull/3735))
- **agent-framework-core**: [BREAKING] Standardize TypeVar naming convention (`TName``NameT`) ([#3770](https://github.com/microsoft/agent-framework/pull/3770))
- **agent-framework-core**: [BREAKING] Refactor workflow events to unified discriminated union pattern ([#3690](https://github.com/microsoft/agent-framework/pull/3690))
- **agent-framework-core**: [BREAKING] Refactor `SharedState` to `State` with sync methods and superstep caching ([#3667](https://github.com/microsoft/agent-framework/pull/3667))
- **agent-framework-core**: [BREAKING] Move single-config fluent methods to constructor parameters ([#3693](https://github.com/microsoft/agent-framework/pull/3693))
- **agent-framework-core**: [BREAKING] Types API Review improvements ([#3647](https://github.com/microsoft/agent-framework/pull/3647))
- **agent-framework-core**: [BREAKING] Fix workflow as agent streaming output ([#3649](https://github.com/microsoft/agent-framework/pull/3649))
- **agent-framework-orchestrations**: [BREAKING] Move orchestrations to dedicated package ([#3685](https://github.com/microsoft/agent-framework/pull/3685))
- **agent-framework-core**: [BREAKING] Remove workflow register factory methods; update tests and samples ([#3781](https://github.com/microsoft/agent-framework/pull/3781))
- **agent-framework-core**: Include sub-workflow structure in graph signature for checkpoint validation ([#3783](https://github.com/microsoft/agent-framework/pull/3783))
- **agent-framework-core**: Adjust workflows TypeVars from prefix to suffix naming convention ([#3661](https://github.com/microsoft/agent-framework/pull/3661))
- **agent-framework-purview**: Update CorrelationId ([#3745](https://github.com/microsoft/agent-framework/pull/3745))
- **agent-framework-anthropic**: Added internal kwargs filtering for Anthropic client ([#3544](https://github.com/microsoft/agent-framework/pull/3544))
- **agent-framework-github-copilot**: Updated instructions/system_message logic in GitHub Copilot agent ([#3625](https://github.com/microsoft/agent-framework/pull/3625))
- **agent-framework-mem0**: Disable mem0 telemetry by default ([#3506](https://github.com/microsoft/agent-framework/pull/3506))
### Fixed
- **agent-framework-core**: Fix workflow not pausing when agent calls declaration-only tool ([#3757](https://github.com/microsoft/agent-framework/pull/3757))
- **agent-framework-core**: Fix GroupChat orchestrator message cleanup issue ([#3712](https://github.com/microsoft/agent-framework/pull/3712))
- **agent-framework-core**: Fix HandoffBuilder silently dropping `context_provider` during agent cloning ([#3721](https://github.com/microsoft/agent-framework/pull/3721))
- **agent-framework-core**: Fix subworkflow duplicate request info events ([#3689](https://github.com/microsoft/agent-framework/pull/3689))
- **agent-framework-core**: Fix workflow cancellation not propagating to active executors ([#3663](https://github.com/microsoft/agent-framework/pull/3663))
- **agent-framework-core**: Filter `response_format` from MCP tool call kwargs ([#3494](https://github.com/microsoft/agent-framework/pull/3494))
- **agent-framework-core**: Fix broken Content API imports in Python samples ([#3639](https://github.com/microsoft/agent-framework/pull/3639))
- **agent-framework-core**: Potential fix for clear-text logging of sensitive information ([#3573](https://github.com/microsoft/agent-framework/pull/3573))
- **agent-framework-core**: Skip `model_deployment_name` validation for application endpoints ([#3621](https://github.com/microsoft/agent-framework/pull/3621))
- **agent-framework-azure-ai**: Fix AzureAIClient dropping agent instructions (Responses API) ([#3636](https://github.com/microsoft/agent-framework/pull/3636))
- **agent-framework-azure-ai**: Fix AzureAIAgentClient dropping agent instructions in sequential workflows ([#3563](https://github.com/microsoft/agent-framework/pull/3563))
- **agent-framework-ag-ui**: Fix AG-UI message handling and MCP tool double-call bug ([#3635](https://github.com/microsoft/agent-framework/pull/3635))
- **agent-framework-claude**: Handle API errors in `run_stream()` method ([#3653](https://github.com/microsoft/agent-framework/pull/3653))
- **agent-framework-claude**: Preserve `$defs` in JSON schema for nested Pydantic models ([#3655](https://github.com/microsoft/agent-framework/pull/3655))
## [1.0.0b260130] - 2026-01-30
### Added
@@ -268,7 +319,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- **agent-framework-core**: [BREAKING] Support Magentic agent tool call approvals and plan stalling HITL behavior (#2569)
- **agent-framework-core**: [BREAKING] Standardize orchestration outputs as list of `ChatMessage`; allow agent as group chat manager (#2291)
- **agent-framework-core**: [BREAKING] Standardize orchestration outputs as list of `Message`; allow agent as group chat manager (#2291)
- **agent-framework-core**: [BREAKING] Respond with `AgentRunResponse` including serialized structured output (#2285)
- **observability**: Use `executor_id` and `edge_group_id` as span names for clearer traces (#2538)
- **agent-framework-devui**: Add multimodal input support for workflows and refactor chat input (#2593)
@@ -314,7 +365,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **agent-framework-core**: Fix tool execution bleed-over in aiohttp/Bot Framework scenarios ([#2314](https://github.com/microsoft/agent-framework/pull/2314))
- **agent-framework-core**: `@ai_function` now correctly handles `self` parameter ([#2266](https://github.com/microsoft/agent-framework/pull/2266))
- **agent-framework-core**: Resolve string annotations in `FunctionExecutor` ([#2308](https://github.com/microsoft/agent-framework/pull/2308))
- **agent-framework-core**: Langfuse observability captures ChatAgent system instructions ([#2316](https://github.com/microsoft/agent-framework/pull/2316))
- **agent-framework-core**: Langfuse observability captures Agent system instructions ([#2316](https://github.com/microsoft/agent-framework/pull/2316))
- **agent-framework-core**: Incomplete URL substring sanitization fix ([#2274](https://github.com/microsoft/agent-framework/pull/2274))
- **observability**: Handle datetime serialization in tool results ([#2248](https://github.com/microsoft/agent-framework/pull/2248))
@@ -571,7 +622,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
For more information, see the [announcement blog post](https://devblogs.microsoft.com/foundry/introducing-microsoft-agent-framework-the-open-source-engine-for-agentic-ai-apps/).
[Unreleased]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260130...HEAD
[Unreleased]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260210...HEAD
[1.0.0b260210]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260130...python-1.0.0b260210
[1.0.0b260130]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260128...python-1.0.0b260130
[1.0.0b260128]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260127...python-1.0.0b260128
[1.0.0b260127]: https://github.com/microsoft/agent-framework/compare/python-1.0.0b260123...python-1.0.0b260127
+9 -9
View File
@@ -118,10 +118,10 @@ Prefer attributes over inheritance when parameters are mostly the same:
```python
# ✅ Preferred - using attributes
from agent_framework import ChatMessage
from agent_framework import Message
user_msg = ChatMessage("user", ["Hello, world!"])
asst_msg = ChatMessage("assistant", ["Hello, world!"])
user_msg = Message("user", ["Hello, world!"])
asst_msg = Message("assistant", ["Hello, world!"])
# ❌ Not preferred - unnecessary inheritance
from agent_framework import UserMessage, AssistantMessage
@@ -157,7 +157,7 @@ The package follows a flat import structure:
- **Core**: Import directly from `agent_framework`
```python
from agent_framework import ChatAgent, tool
from agent_framework import Agent, tool
```
- **Components**: Import from `agent_framework.<component>`
@@ -381,12 +381,12 @@ def create_client(
Use Google-style docstrings for all public APIs:
```python
def create_agent(name: str, chat_client: ChatClientProtocol) -> Agent:
def create_agent(name: str, client: SupportsChatGetResponse) -> Agent:
"""Create a new agent with the specified configuration.
Args:
name: The name of the agent.
chat_client: The chat client to use for communication.
client: The chat client to use for communication.
Returns:
True if the strings are the same, False otherwise.
@@ -409,10 +409,10 @@ Define `__all__` in each module to explicitly declare the public API. Avoid usin
```python
# ✅ Preferred - explicit __all__ and imports
__all__ = ["ChatAgent", "ChatMessage", "ChatResponse"]
__all__ = ["Agent", "Message", "ChatResponse"]
from ._agents import ChatAgent
from ._types import ChatMessage, ChatResponse
from ._agents import Agent
from ._types import Message, ChatResponse
# ❌ Avoid - star imports
from ._agents import *
+1 -1
View File
@@ -116,7 +116,7 @@ You will then configure the ChatClient class with the keyword argument `env_file
```python
from agent_framework.openai import OpenAIChatClient
chat_client = OpenAIChatClient(env_file_path="openai.env")
client = OpenAIChatClient(env_file_path="openai.env")
```
## Tests
+15 -15
View File
@@ -62,7 +62,7 @@ You can also override environment variables by explicitly passing configuration
```python
from agent_framework.azure import AzureOpenAIChatClient
chat_client = AzureOpenAIChatClient(
client = AzureOpenAIChatClient(
api_key='',
endpoint='',
deployment_name='',
@@ -78,12 +78,12 @@ Create agents and invoke them directly:
```python
import asyncio
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
async def main():
agent = ChatAgent(
chat_client=OpenAIChatClient(),
agent = Agent(
client=OpenAIChatClient(),
instructions="""
1) A robot may not injure a human being...
2) A robot must obey orders given it by human beings...
@@ -106,15 +106,15 @@ You can use the chat client classes directly for advanced workflows:
```python
import asyncio
from agent_framework import ChatMessage
from agent_framework import Message
from agent_framework.openai import OpenAIChatClient
async def main():
client = OpenAIChatClient()
messages = [
ChatMessage("system", ["You are a helpful assistant."]),
ChatMessage("user", ["Write a haiku about Agent Framework."])
Message("system", ["You are a helpful assistant."]),
Message("user", ["Write a haiku about Agent Framework."])
]
response = await client.get_response(messages)
@@ -140,7 +140,7 @@ import asyncio
from typing import Annotated
from random import randint
from pydantic import Field
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
@@ -162,8 +162,8 @@ def get_menu_specials() -> str:
async def main():
agent = ChatAgent(
chat_client=OpenAIChatClient(),
agent = Agent(
client=OpenAIChatClient(),
instructions="You are a helpful assistant that can provide weather and restaurant information.",
tools=[get_weather, get_menu_specials]
)
@@ -189,20 +189,20 @@ Coordinate multiple agents to collaborate on complex tasks using orchestration p
```python
import asyncio
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.openai import OpenAIChatClient
async def main():
# Create specialized agents
writer = ChatAgent(
chat_client=OpenAIChatClient(),
writer = Agent(
client=OpenAIChatClient(),
name="Writer",
instructions="You are a creative content writer. Generate and refine slogans based on feedback."
)
reviewer = ChatAgent(
chat_client=OpenAIChatClient(),
reviewer = Agent(
client=OpenAIChatClient(),
name="Reviewer",
instructions="You are a critical reviewer. Provide detailed feedback on proposed slogans."
)
@@ -2,7 +2,7 @@
import importlib.metadata
from ._agent import A2AAgent
from ._agent import A2AAgent, A2AContinuationToken
try:
__version__ = importlib.metadata.version(__name__)
@@ -11,5 +11,6 @@ except importlib.metadata.PackageNotFoundError:
__all__ = [
"A2AAgent",
"A2AContinuationToken",
"__version__",
]
+149 -95
View File
@@ -7,7 +7,7 @@ import json
import re
import uuid
from collections.abc import AsyncIterable, Awaitable, Sequence
from typing import Any, Final, Literal, cast, overload
from typing import Any, Final, Literal, overload
import httpx
from a2a.client import Client, ClientConfig, ClientFactory, minimal_agent_card
@@ -18,8 +18,9 @@ from a2a.types import (
FilePart,
FileWithBytes,
FileWithUri,
Message,
Task,
TaskIdParams,
TaskQueryParams,
TaskState,
TextPart,
TransportProtocol,
@@ -32,23 +33,41 @@ from agent_framework import (
AgentResponseUpdate,
AgentThread,
BaseAgent,
ChatMessage,
Content,
ContinuationToken,
Message,
ResponseStream,
normalize_messages,
prepend_agent_framework_to_user_agent,
)
from agent_framework.observability import AgentTelemetryLayer
__all__ = ["A2AAgent"]
__all__ = ["A2AAgent", "A2AContinuationToken"]
URI_PATTERN = re.compile(r"^data:(?P<media_type>[^;]+);base64,(?P<base64_data>[A-Za-z0-9+/=]+)$")
class A2AContinuationToken(ContinuationToken):
"""Continuation token for A2A protocol long-running tasks."""
task_id: str
"""A2A protocol task ID."""
context_id: str
"""A2A protocol context ID."""
TERMINAL_TASK_STATES = [
TaskState.completed,
TaskState.failed,
TaskState.canceled,
TaskState.rejected,
]
IN_PROGRESS_TASK_STATES = [
TaskState.submitted,
TaskState.working,
TaskState.input_required,
TaskState.auth_required,
]
def _get_uri_data(uri: str) -> str:
@@ -63,7 +82,7 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
"""Agent2Agent (A2A) protocol implementation.
Wraps an A2A Client to connect the Agent Framework with external A2A-compliant agents
via HTTP/JSON-RPC. Converts framework ChatMessages to A2A Messages on send, and converts
via HTTP/JSON-RPC. Converts framework Messages to A2A Messages on send, and converts
A2A responses (Messages/Tasks) back to framework types. Inherits BaseAgent capabilities
while managing the underlying A2A protocol communication.
@@ -189,107 +208,89 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
@overload
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: Literal[False] = ...,
thread: AgentThread | None = None,
continuation_token: A2AContinuationToken | None = None,
background: bool = False,
**kwargs: Any,
) -> Awaitable[AgentResponse[Any]]: ...
@overload
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: Literal[True],
thread: AgentThread | None = None,
continuation_token: A2AContinuationToken | None = None,
background: bool = False,
**kwargs: Any,
) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: ...
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: bool = False,
thread: AgentThread | None = None,
continuation_token: A2AContinuationToken | None = None,
background: bool = False,
**kwargs: Any,
) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
"""Get a response from the agent.
This method returns the final result of the agent's execution
as a single AgentResponse object when stream=False. When stream=True,
it returns a ResponseStream that yields AgentResponseUpdate objects.
Args:
messages: The message(s) to send to the agent.
Keyword Args:
stream: Whether to stream the response. Defaults to False.
thread: The conversation thread associated with the message(s).
continuation_token: Optional token to resume a long-running task
instead of starting a new one.
background: When True, in-progress task updates surface continuation
tokens so the caller can poll or resubscribe later. When False
(default), the agent internally waits for the task to complete.
kwargs: Additional keyword arguments.
Returns:
When stream=False: An Awaitable[AgentResponse].
When stream=True: A ResponseStream of AgentResponseUpdate items.
"""
if continuation_token is not None:
a2a_stream: AsyncIterable[Any] = self.client.resubscribe(TaskIdParams(id=continuation_token["task_id"]))
else:
normalized_messages = normalize_messages(messages)
a2a_message = self._prepare_message_for_a2a(normalized_messages[-1])
a2a_stream = self.client.send_message(a2a_message)
response = ResponseStream(
self._map_a2a_stream(a2a_stream, background=background),
finalizer=AgentResponse.from_updates,
)
if stream:
return self._run_stream_impl(messages=messages, thread=thread, **kwargs)
return self._run_impl(messages=messages, thread=thread, **kwargs)
return response
return response.get_final_response()
async def _run_impl(
async def _map_a2a_stream(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
a2a_stream: AsyncIterable[Any],
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AgentResponse[Any]:
"""Non-streaming implementation of run."""
# Collect all updates and use framework to consolidate updates into response
updates: list[AgentResponseUpdate] = []
async for update in self._stream_updates(messages, thread=thread, **kwargs):
updates.append(update)
return AgentResponse.from_updates(updates)
def _run_stream_impl(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]:
"""Streaming implementation of run."""
def _finalize(updates: Sequence[AgentResponseUpdate]) -> AgentResponse[Any]:
return AgentResponse.from_updates(list(updates))
return ResponseStream(self._stream_updates(messages, thread=thread, **kwargs), finalizer=_finalize)
async def _stream_updates(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
background: bool = False,
) -> AsyncIterable[AgentResponseUpdate]:
"""Internal method to stream updates from the A2A agent.
"""Map raw A2A protocol items to AgentResponseUpdates.
Args:
messages: The message(s) to send to the agent.
a2a_stream: The raw A2A event stream.
Keyword Args:
thread: The conversation thread associated with the message(s).
kwargs: Additional keyword arguments.
Yields:
AgentResponseUpdate items from the A2A agent.
background: When False, in-progress task updates are silently
consumed (the stream keeps iterating until a terminal state).
When True, they are yielded with a continuation token.
"""
normalized_messages = normalize_messages(messages)
a2a_message = self._prepare_message_for_a2a(normalized_messages[-1])
response_stream = self.client.send_message(a2a_message)
async for item in response_stream:
if isinstance(item, Message):
async for item in a2a_stream:
if isinstance(item, A2AMessage):
# Process A2A Message
contents = self._parse_contents_from_a2a(item.parts)
yield AgentResponseUpdate(
@@ -300,37 +301,86 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
)
elif isinstance(item, tuple) and len(item) == 2: # ClientEvent = (Task, UpdateEvent)
task, _update_event = item
if isinstance(task, Task) and task.status.state in TERMINAL_TASK_STATES:
# Convert Task artifacts to ChatMessages and yield as separate updates
task_messages = self._parse_messages_from_task(task)
if task_messages:
for message in task_messages:
# Use the artifact's ID from raw_representation as message_id for unique identification
artifact_id = getattr(message.raw_representation, "artifact_id", None)
yield AgentResponseUpdate(
contents=message.contents,
role=message.role,
response_id=task.id,
message_id=artifact_id,
raw_representation=task,
)
else:
# Empty task
yield AgentResponseUpdate(
contents=[],
role="assistant",
response_id=task.id,
raw_representation=task,
)
if isinstance(task, Task):
for update in self._updates_from_task(task, background=background):
yield update
else:
# Unknown response type
msg = f"Only Message and Task responses are supported from A2A agents. Received: {type(item)}"
raise NotImplementedError(msg)
def _prepare_message_for_a2a(self, message: ChatMessage) -> A2AMessage:
"""Prepare a ChatMessage for the A2A protocol.
# ------------------------------------------------------------------
# Task helpers
# ------------------------------------------------------------------
Transforms Agent Framework ChatMessage objects into A2A protocol Messages by:
def _updates_from_task(self, task: Task, *, background: bool = False) -> list[AgentResponseUpdate]:
"""Convert an A2A Task into AgentResponseUpdate(s).
Terminal tasks produce updates from their artifacts/history.
In-progress tasks produce a continuation token update only when
``background=True``; otherwise they are silently skipped so the
caller keeps consuming the stream until completion.
"""
if task.status.state in TERMINAL_TASK_STATES:
task_messages = self._parse_messages_from_task(task)
if task_messages:
return [
AgentResponseUpdate(
contents=message.contents,
role=message.role,
response_id=task.id,
message_id=getattr(message.raw_representation, "artifact_id", None),
raw_representation=task,
)
for message in task_messages
]
return [AgentResponseUpdate(contents=[], role="assistant", response_id=task.id, raw_representation=task)]
if background and task.status.state in IN_PROGRESS_TASK_STATES:
token = self._build_continuation_token(task)
return [
AgentResponseUpdate(
contents=[],
role="assistant",
response_id=task.id,
continuation_token=token,
raw_representation=task,
)
]
return []
@staticmethod
def _build_continuation_token(task: Task) -> A2AContinuationToken | None:
"""Build an A2AContinuationToken from an A2A Task if it is still in progress."""
if task.status.state in IN_PROGRESS_TASK_STATES:
return A2AContinuationToken(task_id=task.id, context_id=task.context_id)
return None
async def poll_task(self, continuation_token: A2AContinuationToken) -> AgentResponse[Any]:
"""Poll for the current state of a long-running A2A task.
Unlike ``run(continuation_token=...)``, which resubscribes to the SSE
stream, this performs a single request to retrieve the task state.
Args:
continuation_token: A token previously obtained from a response's
``continuation_token`` field.
Returns:
An AgentResponse whose ``continuation_token`` is set when the task
is still in progress, or ``None`` when it has reached a terminal state.
"""
task_id = continuation_token["task_id"]
task = await self.client.get_task(TaskQueryParams(id=task_id))
updates = self._updates_from_task(task, background=True)
if updates:
return AgentResponse.from_updates(updates)
return AgentResponse(messages=[], response_id=task.id, raw_representation=task)
def _prepare_message_for_a2a(self, message: Message) -> A2AMessage:
"""Prepare a Message for the A2A protocol.
Transforms Agent Framework Message objects into A2A protocol Messages by:
- Converting all message contents to appropriate A2A Part types
- Mapping text content to TextPart objects
- Converting file references (URI/data/hosted_file) to FilePart objects
@@ -339,7 +389,7 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
"""
parts: list[A2APart] = []
if not message.contents:
raise ValueError("ChatMessage.contents is empty; cannot convert to A2AMessage.")
raise ValueError("Message.contents is empty; cannot convert to A2AMessage.")
# Process ALL contents
for content in message.contents:
@@ -401,11 +451,15 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
case _:
raise ValueError(f"Unknown content type: {content.type}")
# Exclude framework-internal keys (e.g. attribution) from wire metadata
internal_keys = {"_attribution"}
metadata = {k: v for k, v in message.additional_properties.items() if k not in internal_keys} or None
return A2AMessage(
role=A2ARole("user"),
parts=parts,
message_id=message.message_id or uuid.uuid4().hex,
metadata=cast(dict[str, Any], message.additional_properties),
metadata=metadata,
)
def _parse_contents_from_a2a(self, parts: Sequence[A2APart]) -> list[Content]:
@@ -457,9 +511,9 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
raise ValueError(f"Unknown Part kind: {inner_part.kind}")
return contents
def _parse_messages_from_task(self, task: Task) -> list[ChatMessage]:
"""Parse A2A Task artifacts into ChatMessages with ASSISTANT role."""
messages: list[ChatMessage] = []
def _parse_messages_from_task(self, task: Task) -> list[Message]:
"""Parse A2A Task artifacts into Messages with ASSISTANT role."""
messages: list[Message] = []
if task.artifacts is not None:
for artifact in task.artifacts:
@@ -469,7 +523,7 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
history_item = task.history[-1]
contents = self._parse_contents_from_a2a(history_item.parts)
messages.append(
ChatMessage(
Message(
role="assistant" if history_item.role == A2ARole.agent else "user",
contents=contents,
raw_representation=history_item,
@@ -478,10 +532,10 @@ class A2AAgent(AgentTelemetryLayer, BaseAgent):
return messages
def _parse_message_from_artifact(self, artifact: Artifact) -> ChatMessage:
"""Parse A2A Artifact into ChatMessage using part contents."""
def _parse_message_from_artifact(self, artifact: Artifact) -> Message:
"""Parse A2A Artifact into Message using part contents."""
contents = self._parse_contents_from_a2a(artifact.parts)
return ChatMessage(
return Message(
role="assistant",
contents=contents,
raw_representation=artifact,
+2 -2
View File
@@ -4,7 +4,7 @@ description = "A2A integration for Microsoft Agent Framework."
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
readme = "README.md"
requires-python = ">=3.10"
version = "1.0.0b260130"
version = "1.0.0b260210"
license-files = ["LICENSE"]
urls.homepage = "https://aka.ms/agent-framework"
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
@@ -23,7 +23,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
"agent-framework-core>=1.0.0b260130",
"agent-framework-core>=1.0.0b260210",
"a2a-sdk>=0.3.5",
]
+203 -17
View File
@@ -12,23 +12,24 @@ from a2a.types import (
DataPart,
FilePart,
FileWithUri,
Message,
Part,
Task,
TaskState,
TaskStatus,
TextPart,
)
from a2a.types import Message as A2AMessage
from a2a.types import Role as A2ARole
from agent_framework import (
AgentResponse,
AgentResponseUpdate,
ChatMessage,
Content,
Message,
)
from agent_framework.a2a import A2AAgent
from pytest import fixture, raises
from agent_framework_a2a import A2AContinuationToken
from agent_framework_a2a._agent import _get_uri_data # type: ignore
@@ -38,6 +39,8 @@ class MockA2AClient:
def __init__(self) -> None:
self.call_count: int = 0
self.responses: list[Any] = []
self.resubscribe_responses: list[Any] = []
self.get_task_response: Task | None = None
def add_message_response(self, message_id: str, text: str, role: str = "agent") -> None:
"""Add a mock Message response."""
@@ -46,7 +49,7 @@ class MockA2AClient:
text_part = Part(root=TextPart(text=text))
# Create actual Message instance
message = Message(
message = A2AMessage(
message_id=message_id, role=A2ARole.agent if role == "agent" else A2ARole.user, parts=[text_part]
)
self.responses.append(message)
@@ -80,6 +83,18 @@ class MockA2AClient:
client_event = (task, update_event)
self.responses.append(client_event)
def add_in_progress_task_response(
self,
task_id: str,
context_id: str = "test-context",
state: TaskState = TaskState.working,
) -> None:
"""Add a mock in-progress Task response (non-terminal)."""
status = TaskStatus(state=state, message=None)
task = Task(id=task_id, context_id=context_id, status=status)
client_event = (task, None)
self.responses.append(client_event)
async def send_message(self, message: Any) -> AsyncIterator[Any]:
"""Mock send_message method that yields responses."""
self.call_count += 1
@@ -88,6 +103,22 @@ class MockA2AClient:
response = self.responses.pop(0)
yield response
async def resubscribe(self, request: Any) -> AsyncIterator[Any]:
"""Mock resubscribe method that yields responses."""
self.call_count += 1
for response in self.resubscribe_responses:
yield response
self.resubscribe_responses.clear()
async def get_task(self, request: Any) -> Task:
"""Mock get_task method that returns a task."""
self.call_count += 1
if self.get_task_response is not None:
return self.get_task_response
msg = "No get_task response configured"
raise ValueError(msg)
@fixture
def mock_a2a_client() -> MockA2AClient:
@@ -250,7 +281,7 @@ def test_parse_message_from_artifact(a2a_agent: A2AAgent) -> None:
result = a2a_agent._parse_message_from_artifact(artifact)
assert isinstance(result, ChatMessage)
assert isinstance(result, Message)
assert result.role == "assistant"
assert result.text == "Artifact content"
assert result.raw_representation == artifact
@@ -293,9 +324,9 @@ def test_parse_contents_from_a2a_conversion(a2a_agent: A2AAgent) -> None:
def test_prepare_message_for_a2a_with_error_content(a2a_agent: A2AAgent) -> None:
"""Test _prepare_message_for_a2a with ErrorContent."""
# Create ChatMessage with ErrorContent
# Create Message with ErrorContent
error_content = Content.from_error(message="Test error message")
message = ChatMessage(role="user", contents=[error_content])
message = Message(role="user", contents=[error_content])
# Convert to A2A message
a2a_message = a2a_agent._prepare_message_for_a2a(message)
@@ -308,9 +339,9 @@ def test_prepare_message_for_a2a_with_error_content(a2a_agent: A2AAgent) -> None
def test_prepare_message_for_a2a_with_uri_content(a2a_agent: A2AAgent) -> None:
"""Test _prepare_message_for_a2a with UriContent."""
# Create ChatMessage with UriContent
# Create Message with UriContent
uri_content = Content.from_uri(uri="http://example.com/file.pdf", media_type="application/pdf")
message = ChatMessage(role="user", contents=[uri_content])
message = Message(role="user", contents=[uri_content])
# Convert to A2A message
a2a_message = a2a_agent._prepare_message_for_a2a(message)
@@ -324,9 +355,9 @@ def test_prepare_message_for_a2a_with_uri_content(a2a_agent: A2AAgent) -> None:
def test_prepare_message_for_a2a_with_data_content(a2a_agent: A2AAgent) -> None:
"""Test _prepare_message_for_a2a with DataContent."""
# Create ChatMessage with DataContent (base64 data URI)
# Create Message with DataContent (base64 data URI)
data_content = Content.from_uri(uri="data:text/plain;base64,SGVsbG8gV29ybGQ=", media_type="text/plain")
message = ChatMessage(role="user", contents=[data_content])
message = Message(role="user", contents=[data_content])
# Convert to A2A message
a2a_message = a2a_agent._prepare_message_for_a2a(message)
@@ -339,11 +370,11 @@ def test_prepare_message_for_a2a_with_data_content(a2a_agent: A2AAgent) -> None:
def test_prepare_message_for_a2a_empty_contents_raises_error(a2a_agent: A2AAgent) -> None:
"""Test _prepare_message_for_a2a with empty contents raises ValueError."""
# Create ChatMessage with no contents
message = ChatMessage(role="user", contents=[])
# Create Message with no contents
message = Message(role="user", contents=[])
# Should raise ValueError for empty contents
with raises(ValueError, match="ChatMessage.contents is empty"):
with raises(ValueError, match="Message.contents is empty"):
a2a_agent._prepare_message_for_a2a(message)
@@ -401,12 +432,12 @@ async def test_context_manager_no_cleanup_when_no_http_client() -> None:
def test_prepare_message_for_a2a_with_multiple_contents() -> None:
"""Test conversion of ChatMessage with multiple contents."""
"""Test conversion of Message with multiple contents."""
agent = A2AAgent(client=MagicMock(), _http_client=None)
# Create message with multiple content types
message = ChatMessage(
message = Message(
role="user",
contents=[
Content.from_text(text="Here's the analysis:"),
@@ -458,12 +489,12 @@ def test_parse_contents_from_a2a_unknown_part_kind() -> None:
def test_prepare_message_for_a2a_with_hosted_file() -> None:
"""Test conversion of ChatMessage with HostedFileContent to A2A message."""
"""Test conversion of Message with HostedFileContent to A2A message."""
agent = A2AAgent(client=MagicMock(), _http_client=None)
# Create message with hosted file content
message = ChatMessage(
message = Message(
role="user",
contents=[Content.from_hosted_file(file_id="hosted://storage/document.pdf")],
)
@@ -598,3 +629,158 @@ def test_a2a_agent_initialization_with_timeout_parameter() -> None:
# Verify it's an httpx.Timeout object with our custom timeout applied to all components
assert isinstance(timeout_arg, httpx.Timeout)
# region Continuation Token Tests
async def test_working_task_emits_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that a working (non-terminal) task yields an update with a continuation token when background=True."""
mock_a2a_client.add_in_progress_task_response("task-wip", context_id="ctx-1", state=TaskState.working)
response = await a2a_agent.run("Start long task", background=True)
assert isinstance(response, AgentResponse)
assert response.continuation_token is not None
assert response.continuation_token["task_id"] == "task-wip"
assert response.continuation_token["context_id"] == "ctx-1"
async def test_submitted_task_emits_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that a submitted task yields a continuation token when background=True."""
mock_a2a_client.add_in_progress_task_response("task-sub", state=TaskState.submitted)
response = await a2a_agent.run("Submit task", background=True)
assert response.continuation_token is not None
assert response.continuation_token["task_id"] == "task-sub"
async def test_input_required_task_emits_continuation_token(
a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient
) -> None:
"""Test that an input_required task yields a continuation token when background=True."""
mock_a2a_client.add_in_progress_task_response("task-input", state=TaskState.input_required)
response = await a2a_agent.run("Need input", background=True)
assert response.continuation_token is not None
assert response.continuation_token["task_id"] == "task-input"
async def test_working_task_no_token_without_background(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that background=False (default) does not emit continuation tokens for in-progress tasks."""
mock_a2a_client.add_in_progress_task_response("task-fg", context_id="ctx-fg", state=TaskState.working)
response = await a2a_agent.run("Foreground task")
assert response.continuation_token is None
async def test_completed_task_has_no_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that a completed task does not set a continuation token."""
mock_a2a_client.add_task_response("task-done", [{"id": "art-1", "content": "Result"}])
response = await a2a_agent.run("Quick task")
assert response.continuation_token is None
assert len(response.messages) == 1
assert response.messages[0].text == "Result"
async def test_streaming_emits_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that streaming with background=True yields updates with continuation tokens."""
mock_a2a_client.add_in_progress_task_response("task-stream", context_id="ctx-s", state=TaskState.working)
updates: list[AgentResponseUpdate] = []
async for update in a2a_agent.run("Stream task", stream=True, background=True):
updates.append(update)
assert len(updates) == 1
assert updates[0].continuation_token is not None
assert updates[0].continuation_token["task_id"] == "task-stream"
assert updates[0].continuation_token["context_id"] == "ctx-s"
async def test_resume_via_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that run() with continuation_token uses resubscribe instead of send_message."""
# Set up the resubscribe response (completed task)
status = TaskStatus(state=TaskState.completed, message=None)
artifact = Artifact(
artifact_id="art-resume",
name="result",
parts=[Part(root=TextPart(text="Resumed result"))],
)
task = Task(id="task-resume", context_id="ctx-r", status=status, artifacts=[artifact])
mock_a2a_client.resubscribe_responses.append((task, None))
token = A2AContinuationToken(task_id="task-resume", context_id="ctx-r")
response = await a2a_agent.run(continuation_token=token)
assert isinstance(response, AgentResponse)
assert len(response.messages) == 1
assert response.messages[0].text == "Resumed result"
assert response.continuation_token is None
async def test_resume_streaming_via_continuation_token(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test that streaming run() with continuation_token and background=True uses resubscribe."""
# Still working
status_wip = TaskStatus(state=TaskState.working, message=None)
task_wip = Task(id="task-rs", context_id="ctx-rs", status=status_wip)
# Then completed
status_done = TaskStatus(state=TaskState.completed, message=None)
artifact = Artifact(
artifact_id="art-rs",
name="result",
parts=[Part(root=TextPart(text="Stream resumed"))],
)
task_done = Task(id="task-rs", context_id="ctx-rs", status=status_done, artifacts=[artifact])
mock_a2a_client.resubscribe_responses.extend([(task_wip, None), (task_done, None)])
token = A2AContinuationToken(task_id="task-rs", context_id="ctx-rs")
updates: list[AgentResponseUpdate] = []
async for update in a2a_agent.run(stream=True, continuation_token=token, background=True):
updates.append(update)
# First update: in-progress with token, second: completed with content
assert len(updates) == 2
assert updates[0].continuation_token is not None
assert updates[0].continuation_token["task_id"] == "task-rs"
assert updates[1].continuation_token is None
assert updates[1].contents[0].text == "Stream resumed"
async def test_poll_task_in_progress(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test poll_task returns continuation token when task is still in progress."""
status = TaskStatus(state=TaskState.working, message=None)
mock_a2a_client.get_task_response = Task(id="task-poll", context_id="ctx-p", status=status)
token = A2AContinuationToken(task_id="task-poll", context_id="ctx-p")
response = await a2a_agent.poll_task(token)
assert response.continuation_token is not None
assert response.continuation_token["task_id"] == "task-poll"
async def test_poll_task_completed(a2a_agent: A2AAgent, mock_a2a_client: MockA2AClient) -> None:
"""Test poll_task returns result with no continuation token when task is complete."""
status = TaskStatus(state=TaskState.completed, message=None)
artifact = Artifact(
artifact_id="art-poll",
name="result",
parts=[Part(root=TextPart(text="Poll result"))],
)
mock_a2a_client.get_task_response = Task(
id="task-poll-done", context_id="ctx-pd", status=status, artifacts=[artifact]
)
token = A2AContinuationToken(task_id="task-poll-done", context_id="ctx-pd")
response = await a2a_agent.poll_task(token)
assert response.continuation_token is None
assert len(response.messages) == 1
assert response.messages[0].text == "Poll result"
# endregion
+6 -6
View File
@@ -14,15 +14,15 @@ pip install agent-framework-ag-ui
```python
from fastapi import FastAPI
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
# Create your agent
agent = ChatAgent(
agent = Agent(
name="my_agent",
instructions="You are a helpful assistant.",
chat_client=AzureOpenAIChatClient(
client=AzureOpenAIChatClient(
endpoint="https://your-resource.openai.azure.com/",
deployment_name="gpt-4o-mini",
api_key="your-api-key",
@@ -58,7 +58,7 @@ The `AGUIChatClient` supports:
- Streaming and non-streaming responses
- Hybrid tool execution (client-side + server-side tools)
- Automatic thread management for conversation continuity
- Integration with `ChatAgent` for client-side history management
- Integration with `Agent` for client-side history management
## Documentation
@@ -91,7 +91,7 @@ The AG-UI endpoint does not enforce authentication by default. **For production
import os
from fastapi import Depends, FastAPI, HTTPException, Security
from fastapi.security import APIKeyHeader
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
# Configure API key authentication
@@ -104,7 +104,7 @@ async def verify_api_key(api_key: str | None = Security(API_KEY_HEADER)) -> None
raise HTTPException(status_code=401, detail="Invalid or missing API key")
# Create agent and app
agent = ChatAgent(name="my_agent", instructions="...", chat_client=...)
agent = Agent(name="my_agent", instructions="...", client=...)
app = FastAPI()
# Register endpoint WITH authentication
@@ -15,11 +15,11 @@ from typing import TYPE_CHECKING, Any, Generic, TypedDict, cast
import httpx
from agent_framework import (
BaseChatClient,
ChatMessage,
ChatResponse,
ChatResponseUpdate,
Content,
FunctionTool,
Message,
ResponseStream,
)
from agent_framework._middleware import ChatMiddlewareLayer
@@ -69,10 +69,10 @@ AGUIChatOptionsT = TypeVar(
)
def _apply_server_function_call_unwrap(chat_client: BaseChatClientT) -> BaseChatClientT:
def _apply_server_function_call_unwrap(client: BaseChatClientT) -> BaseChatClientT:
"""Class decorator that unwraps server-side function calls after tool handling."""
original_get_response = chat_client.get_response
original_get_response = client.get_response
@wraps(original_get_response)
def response_wrapper(
@@ -105,8 +105,8 @@ def _apply_server_function_call_unwrap(chat_client: BaseChatClientT) -> BaseChat
_unwrap_server_function_call_contents(cast(MutableSequence[Content | dict[str, Any]], update.contents))
return update
chat_client.get_response = response_wrapper # type: ignore[assignment]
return chat_client
client.get_response = response_wrapper # type: ignore[assignment]
return client
@_apply_server_function_call_unwrap
@@ -130,8 +130,8 @@ class AGUIChatClient(
This client sends exactly the messages it receives to the server. It does NOT
automatically maintain conversation history. The server must handle history via thread_id.
For stateless servers: Use ChatAgent wrapper which will send full message history on each
request. However, even with ChatAgent, the server must echo back all context for the
For stateless servers: Use Agent wrapper which will send full message history on each
request. However, even with Agent, the server must echo back all context for the
agent to maintain history across turns.
Important: Tool Handling (Hybrid Execution - matches .NET)
@@ -140,7 +140,7 @@ class AGUIChatClient(
3. When LLM calls a client tool, function invocation executes it locally
4. Both client and server tools work together (hybrid pattern)
The wrapping ChatAgent's function invocation handles client tool execution
The wrapping Agent's function invocation handles client tool execution
automatically when the server's LLM decides to call them.
Examples:
@@ -162,18 +162,18 @@ class AGUIChatClient(
metadata={"thread_id": thread_id}
)
Recommended usage with ChatAgent (client manages history):
Recommended usage with Agent (client manages history):
.. code-block:: python
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.ag_ui import AGUIChatClient
client = AGUIChatClient(endpoint="http://localhost:8888/")
agent = ChatAgent(name="assistant", client=client)
agent = Agent(name="assistant", client=client)
thread = await agent.get_new_thread()
# ChatAgent automatically maintains history and sends full context
# Agent automatically maintains history and sends full context
response = await agent.run("Hello!", thread=thread)
response2 = await agent.run("How are you?", thread=thread)
@@ -282,9 +282,7 @@ class AGUIChatClient(
logger = get_logger()
logger.debug(f"[AGUIChatClient] Registered server placeholder: {tool_name}")
def _extract_state_from_messages(
self, messages: Sequence[ChatMessage]
) -> tuple[list[ChatMessage], dict[str, Any] | None]:
def _extract_state_from_messages(self, messages: Sequence[Message]) -> tuple[list[Message], dict[str, Any] | None]:
"""Extract state from last message if present.
Args:
@@ -319,11 +317,11 @@ class AGUIChatClient(
return list(messages), None
def _convert_messages_to_agui_format(self, messages: list[ChatMessage]) -> list[dict[str, Any]]:
def _convert_messages_to_agui_format(self, messages: list[Message]) -> list[dict[str, Any]]:
"""Convert Agent Framework messages to AG-UI format.
Args:
messages: List of ChatMessage objects
messages: List of Message objects
Returns:
List of AG-UI formatted message dictionaries
@@ -353,7 +351,7 @@ class AGUIChatClient(
def _inner_get_response(
self,
*,
messages: Sequence[ChatMessage],
messages: Sequence[Message],
stream: bool = False,
options: Mapping[str, Any],
**kwargs: Any,
@@ -393,7 +391,7 @@ class AGUIChatClient(
async def _streaming_impl(
self,
*,
messages: Sequence[ChatMessage],
messages: Sequence[Message],
options: Mapping[str, Any],
**kwargs: Any,
) -> AsyncIterable[ChatResponseUpdate]:
@@ -415,7 +413,7 @@ class AGUIChatClient(
agui_messages = self._convert_messages_to_agui_format(messages_to_send)
# Send client tools to server so LLM knows about them
# Client tools execute via ChatAgent's function invocation wrapper
# Client tools execute via Agent's function invocation wrapper
agui_tools = convert_tools_to_agui_format(options.get("tools"))
# Build set of client tool names (matches .NET clientToolSet)
@@ -9,8 +9,8 @@ import logging
from typing import Any, cast
from agent_framework import (
ChatMessage,
Content,
Message,
prepare_function_call_results,
)
@@ -25,9 +25,9 @@ from ._utils import (
logger = logging.getLogger(__name__)
def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
def _sanitize_tool_history(messages: list[Message]) -> list[Message]:
"""Normalize tool ordering and inject synthetic results for AG-UI edge cases."""
sanitized: list[ChatMessage] = []
sanitized: list[Message] = []
pending_tool_call_ids: set[str] | None = None
pending_confirm_changes_id: str | None = None
@@ -60,7 +60,7 @@ def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
]
if filtered_contents:
# Create a new message without confirm_changes to avoid mutating the input
filtered_msg = ChatMessage(role=msg.role, contents=filtered_contents)
filtered_msg = Message(role=msg.role, contents=filtered_contents)
sanitized.append(filtered_msg)
# If no contents left after filtering, don't append anything
@@ -99,7 +99,7 @@ def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
if pending_confirm_changes_id and approval_accepted is not None:
logger.info(f"Injecting synthetic tool result for confirm_changes call_id={pending_confirm_changes_id}")
synthetic_result = ChatMessage(
synthetic_result = Message(
role="tool",
contents=[
Content.from_function_result(
@@ -128,7 +128,7 @@ def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
logger.info(
f"Injecting synthetic tool result for confirm_changes call_id={pending_confirm_changes_id}"
)
synthetic_result = ChatMessage(
synthetic_result = Message(
role="tool",
contents=[
Content.from_function_result(
@@ -152,7 +152,7 @@ def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
)
for pending_call_id in pending_tool_call_ids:
logger.info(f"Injecting synthetic tool result for pending call_id={pending_call_id}")
synthetic_result = ChatMessage(
synthetic_result = Message(
role="tool",
contents=[
Content.from_function_result(
@@ -196,10 +196,10 @@ def _sanitize_tool_history(messages: list[ChatMessage]) -> list[ChatMessage]:
return sanitized
def _deduplicate_messages(messages: list[ChatMessage]) -> list[ChatMessage]:
def _deduplicate_messages(messages: list[Message]) -> list[Message]:
"""Remove duplicate messages while preserving order."""
seen_keys: dict[Any, int] = {}
unique_messages: list[ChatMessage] = []
unique_messages: list[Message] = []
for idx, msg in enumerate(messages):
role_value = get_role_value(msg)
@@ -256,7 +256,7 @@ def _deduplicate_messages(messages: list[ChatMessage]) -> list[ChatMessage]:
def normalize_agui_input_messages(
messages: list[dict[str, Any]],
) -> tuple[list[ChatMessage], list[dict[str, Any]]]:
) -> tuple[list[Message], list[dict[str, Any]]]:
"""Normalize raw AG-UI messages into provider and snapshot formats."""
provider_messages = agui_messages_to_agent_framework(messages)
provider_messages = _sanitize_tool_history(provider_messages)
@@ -265,14 +265,14 @@ def normalize_agui_input_messages(
return provider_messages, snapshot_messages
def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[ChatMessage]:
def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Message]:
"""Convert AG-UI messages to Agent Framework format.
Args:
messages: List of AG-UI messages
Returns:
List of Agent Framework ChatMessage objects
List of Agent Framework Message objects
"""
def _update_tool_call_arguments(
@@ -367,7 +367,7 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
allowed_keys = set(original_args.keys())
return {key: value for key, value in modified_args.items() if key in allowed_keys}
result: list[ChatMessage] = []
result: list[Message] = []
for msg in messages:
# Handle standard tool result messages early (role="tool") to preserve provider invariants
# This path maps AGUI tool messages to function_result content with the correct tool_call_id
@@ -480,7 +480,7 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
merged_args["steps"] = merged_steps
state_args = merged_args
# Update the ChatMessage tool call with only enabled steps (for LLM context).
# Update the Message tool call with only enabled steps (for LLM context).
# The LLM should only see the steps that were actually approved/executed.
updated_args_for_llm = (
json.dumps(filtered_args)
@@ -510,14 +510,14 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
function_call=func_call_for_approval,
additional_properties={"ag_ui_state_args": state_args} if state_args else None,
)
chat_msg = ChatMessage(
chat_msg = Message(
role="user",
contents=[approval_response],
)
else:
# No matching function call found - this is likely a confirm_changes approval
# Keep the old behavior for backwards compatibility
chat_msg = ChatMessage(
chat_msg = Message(
role="user",
contents=[Content.from_text(text=approval_payload_text)],
additional_properties={"is_tool_result": True, "tool_call_id": str(tool_call_id or "")},
@@ -537,7 +537,7 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
func_result = result_content
else:
func_result = str(result_content)
chat_msg = ChatMessage(
chat_msg = Message(
role="tool",
contents=[Content.from_function_result(call_id=str(tool_call_id), result=func_result)],
)
@@ -553,7 +553,7 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
tool_call_id = msg.get("toolCallId") or msg.get("tool_call_id") or msg.get("actionExecutionId", "")
result_content = msg.get("result", msg.get("content", ""))
chat_msg = ChatMessage(
chat_msg = Message(
role="tool",
contents=[Content.from_function_result(call_id=str(tool_call_id), result=result_content)],
)
@@ -592,7 +592,7 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
arguments=arguments,
)
)
chat_msg = ChatMessage(role="assistant", contents=contents)
chat_msg = Message(role="assistant", contents=contents)
if "id" in msg:
chat_msg.message_id = msg["id"]
result.append(chat_msg)
@@ -622,14 +622,14 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
)
approval_contents.append(approval_response)
chat_msg = ChatMessage(role=role, contents=approval_contents) # type: ignore[call-overload]
chat_msg = Message(role=role, contents=approval_contents) # type: ignore[call-overload]
else:
# Regular text message
content = msg.get("content", "")
if isinstance(content, str):
chat_msg = ChatMessage(role=role, contents=[Content.from_text(text=content)]) # type: ignore[call-overload]
chat_msg = Message(role=role, contents=[Content.from_text(text=content)]) # type: ignore[call-overload]
else:
chat_msg = ChatMessage(role=role, contents=[Content.from_text(text=str(content))]) # type: ignore[call-overload]
chat_msg = Message(role=role, contents=[Content.from_text(text=str(content))]) # type: ignore[call-overload]
if "id" in msg:
chat_msg.message_id = msg["id"]
@@ -639,11 +639,11 @@ def agui_messages_to_agent_framework(messages: list[dict[str, Any]]) -> list[Cha
return result
def agent_framework_messages_to_agui(messages: list[ChatMessage] | list[dict[str, Any]]) -> list[dict[str, Any]]:
def agent_framework_messages_to_agui(messages: list[Message] | list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Convert Agent Framework messages to AG-UI format.
Args:
messages: List of Agent Framework ChatMessage objects or AG-UI dicts (already converted)
messages: List of Agent Framework Message objects or AG-UI dicts (already converted)
Returns:
List of AG-UI message dictionaries
@@ -672,7 +672,7 @@ def agent_framework_messages_to_agui(messages: list[ChatMessage] | list[dict[str
result.append(normalized_msg)
continue
# Convert ChatMessage to AG-UI format
# Convert Message to AG-UI format
role_value: str = msg.role if hasattr(msg.role, "value") else msg.role # type: ignore[assignment]
role = FRAMEWORK_TO_AGUI_ROLE.get(role_value, "user")
@@ -13,8 +13,8 @@ import logging
from typing import Any
from agent_framework import (
ChatMessage,
Content,
Message,
)
from .._utils import get_role_value
@@ -22,7 +22,7 @@ from .._utils import get_role_value
logger = logging.getLogger(__name__)
def pending_tool_call_ids(messages: list[ChatMessage]) -> set[str]:
def pending_tool_call_ids(messages: list[Message]) -> set[str]:
"""Get IDs of tool calls without corresponding results.
Args:
@@ -42,7 +42,7 @@ def pending_tool_call_ids(messages: list[ChatMessage]) -> set[str]:
return pending_ids - resolved_ids
def is_state_context_message(message: ChatMessage) -> bool:
def is_state_context_message(message: Message) -> bool:
"""Check if a message is a state context system message.
Args:
@@ -178,7 +178,7 @@ def build_safe_metadata(thread_metadata: dict[str, Any] | None) -> dict[str, Any
return safe_metadata
def latest_approval_response(messages: list[ChatMessage]) -> Content | None:
def latest_approval_response(messages: list[Message]) -> Content | None:
"""Get the latest approval response from messages.
Args:
@@ -39,7 +39,7 @@ def collect_server_tools(agent: SupportsAgentRun) -> list[Any]:
functions need to be included for tool execution during approval flows.
Args:
agent: Agent instance to collect tools from. Works with ChatAgent
agent: Agent instance to collect tools from. Works with Agent
or any agent with default_options and optional mcp_tools attributes.
Returns:
@@ -53,7 +53,7 @@ def collect_server_tools(agent: SupportsAgentRun) -> list[Any]:
tools_from_agent = default_options.get("tools") if isinstance(default_options, dict) else None
server_tools = list(tools_from_agent) if tools_from_agent else []
# Include functions from connected MCP tools (only available on ChatAgent)
# Include functions from connected MCP tools (only available on Agent)
mcp_tools = getattr(agent, "mcp_tools", None)
if mcp_tools:
server_tools.extend(_collect_mcp_tool_functions(mcp_tools))
@@ -70,19 +70,19 @@ def register_additional_client_tools(agent: SupportsAgentRun, client_tools: list
"""Register client tools as additional declaration-only tools to avoid server execution.
Args:
agent: Agent instance to register tools on. Works with ChatAgent
or any agent with a chat_client attribute.
agent: Agent instance to register tools on. Works with Agent
or any agent with a client attribute.
client_tools: List of client tools to register.
"""
if not client_tools:
return
chat_client = getattr(agent, "chat_client", None)
if chat_client is None:
client = getattr(agent, "client", None)
if client is None:
return
if isinstance(chat_client, BaseChatClient) and chat_client.function_invocation_configuration is not None: # type: ignore[attr-defined]
chat_client.function_invocation_configuration["additional_tools"] = client_tools # type: ignore[attr-defined]
if isinstance(client, BaseChatClient) and client.function_invocation_configuration is not None: # type: ignore[attr-defined]
client.function_invocation_configuration["additional_tools"] = client_tools # type: ignore[attr-defined]
logger.debug(f"[TOOLS] Registered {len(client_tools)} client tools as additional_tools (declaration-only)")
@@ -28,8 +28,8 @@ from ag_ui.core import (
)
from agent_framework import (
AgentThread,
ChatMessage,
Content,
Message,
SupportsAgentRun,
prepare_function_call_results,
)
@@ -195,7 +195,7 @@ class FlowState:
def _create_state_context_message(
current_state: dict[str, Any],
state_schema: dict[str, Any],
) -> ChatMessage | None:
) -> Message | None:
"""Create a system message with current state context.
This injects the current state into the conversation so the model
@@ -206,13 +206,13 @@ def _create_state_context_message(
state_schema: The state schema (used to determine if injection is needed)
Returns:
ChatMessage with state context, or None if not needed
Message with state context, or None if not needed
"""
if not current_state or not state_schema:
return None
state_json = json.dumps(current_state, indent=2)
return ChatMessage(
return Message(
role="system",
contents=[
Content.from_text(
@@ -229,10 +229,10 @@ def _create_state_context_message(
def _inject_state_context(
messages: list[ChatMessage],
messages: list[Message],
current_state: dict[str, Any],
state_schema: dict[str, Any],
) -> list[ChatMessage]:
) -> list[Message]:
"""Inject state context message into messages if appropriate.
The state context is injected before the last user message to give
@@ -592,7 +592,7 @@ async def _resolve_approval_responses(
Args:
messages: List of messages (will be modified in place)
tools: List of available tools
agent: The agent instance (to get chat_client and config)
agent: The agent instance (to get client and config)
run_kwargs: Kwargs for tool execution
"""
fcc_todo = _collect_approval_responses(messages)
@@ -605,12 +605,10 @@ async def _resolve_approval_responses(
# Execute approved tool calls
if approved_responses and tools:
chat_client = getattr(agent, "chat_client", None)
config = normalize_function_invocation_configuration(
getattr(chat_client, "function_invocation_configuration", None)
)
client = getattr(agent, "client", None)
config = normalize_function_invocation_configuration(getattr(client, "function_invocation_configuration", None))
middleware_pipeline = FunctionMiddlewarePipeline(
*getattr(chat_client, "function_middleware", ()),
*getattr(client, "function_middleware", ()),
*run_kwargs.get("middleware", ()),
)
# Filter out AG-UI-specific kwargs that should not be passed to tool execution
@@ -672,7 +670,7 @@ def _convert_approval_results_to_tool_messages(messages: list[Any]) -> None:
This modifies the messages list in place.
Args:
messages: List of ChatMessage objects to process
messages: List of Message objects to process
"""
result: list[Any] = []
@@ -694,11 +692,11 @@ def _convert_approval_results_to_tool_messages(messages: list[Any]) -> None:
# Tool messages first (right after the preceding assistant message per OpenAI requirements)
for func_result in function_results:
result.append(ChatMessage(role="tool", contents=[func_result]))
result.append(Message(role="tool", contents=[func_result]))
# Then user message with remaining content (if any)
if other_contents:
result.append(ChatMessage(role=msg.role, contents=other_contents))
result.append(Message(role=msg.role, contents=other_contents))
messages[:] = result
@@ -793,9 +791,9 @@ async def run_agent_stream(
# Check for structured output mode (skip text content)
skip_text = False
response_format = None
from agent_framework import ChatAgent
from agent_framework import Agent
if isinstance(agent, ChatAgent):
if isinstance(agent, Agent):
response_format = agent.default_options.get("response_format")
skip_text = response_format is not None
@@ -12,7 +12,7 @@ from dataclasses import asdict, is_dataclass
from datetime import date, datetime
from typing import Any
from agent_framework import AgentResponseUpdate, ChatResponseUpdate, FunctionTool, ToolProtocol
from agent_framework import AgentResponseUpdate, ChatResponseUpdate, FunctionTool
# Role mapping constants
AGUI_TO_FRAMEWORK_ROLE: dict[str, str] = {
@@ -200,10 +200,10 @@ def convert_agui_tools_to_agent_framework(
def convert_tools_to_agui_format(
tools: (
ToolProtocol
FunctionTool
| Callable[..., Any]
| MutableMapping[str, Any]
| Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]]
| Sequence[FunctionTool | Callable[..., Any] | MutableMapping[str, Any]]
| None
),
) -> list[dict[str, Any]] | None:
@@ -225,7 +225,7 @@ def convert_tools_to_agui_format(
# Normalize to list
if not isinstance(tools, list):
tool_list: list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] = [tools] # type: ignore[list-item]
tool_list: list[FunctionTool | Callable[..., Any] | MutableMapping[str, Any]] = [tools] # type: ignore[list-item]
else:
tool_list = tools # type: ignore[assignment]
@@ -256,12 +256,8 @@ def convert_tools_to_agui_format(
"parameters": ai_func.parameters(),
}
)
elif isinstance(tool_item, ToolProtocol):
# Handle other ToolProtocol implementations
# For now, we'll skip non-FunctionTool instances as they may not have
# the parameters() method. This matches .NET behavior which only
# converts FunctionToolDeclaration instances.
continue
# Note: dict-based hosted tools (CodeInterpreter, WebSearch, etc.) are passed through
# as-is in the first branch. Non-FunctionTool, non-dict items are skipped.
return results if results else None
@@ -12,7 +12,7 @@ pip install agent-framework-ag-ui
### Using Example Agents with Any Chat Client
All example agents are factory functions that accept any `ChatClientProtocol`-compatible chat client:
All example agents are factory functions that accept any `SupportsChatGetResponse`-compatible chat client:
```python
from fastapi import FastAPI
@@ -38,15 +38,15 @@ add_agent_framework_fastapi_endpoint(app, weather_agent(openai_client), "/weathe
```python
from fastapi import FastAPI
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
# Create your agent
agent = ChatAgent(
agent = Agent(
name="my_agent",
instructions="You are a helpful assistant.",
chat_client=AzureOpenAIChatClient(model_id="gpt-4o"),
client=AzureOpenAIChatClient(model_id="gpt-4o"),
)
# Create FastAPI app and add AG-UI endpoint
@@ -70,21 +70,21 @@ This integration supports all 7 AG-UI features:
## Examples
All example agents are implemented as **factory functions** that accept any chat client implementing `ChatClientProtocol`. This provides maximum flexibility to use Azure OpenAI, OpenAI, Anthropic, or any custom chat client implementation.
All example agents are implemented as **factory functions** that accept any chat client implementing `SupportsChatGetResponse`. This provides maximum flexibility to use Azure OpenAI, OpenAI, Anthropic, or any custom chat client implementation.
### Available Example Agents
Complete examples for all AG-UI features are available:
- `simple_agent(chat_client)` - Basic agentic chat (Feature 1)
- `weather_agent(chat_client)` - Backend tool rendering (Feature 2)
- `human_in_the_loop_agent(chat_client)` - Human-in-the-loop with step customization (Feature 3)
- `task_steps_agent_wrapped(chat_client)` - Agentic generative UI with step execution (Feature 4)
- `ui_generator_agent(chat_client)` - Tool-based generative UI (Feature 5)
- `recipe_agent(chat_client)` - Shared state management (Feature 6)
- `document_writer_agent(chat_client)` - Predictive state updates (Feature 7)
- `research_assistant_agent(chat_client)` - Research with progress events
- `task_planner_agent(chat_client)` - Task planning with approvals
- `simple_agent(client)` - Basic agentic chat (Feature 1)
- `weather_agent(client)` - Backend tool rendering (Feature 2)
- `human_in_the_loop_agent(client)` - Human-in-the-loop with step customization (Feature 3)
- `task_steps_agent_wrapped(client)` - Agentic generative UI with step execution (Feature 4)
- `ui_generator_agent(client)` - Tool-based generative UI (Feature 5)
- `recipe_agent(client)` - Shared state management (Feature 6)
- `document_writer_agent(client)` - Predictive state updates (Feature 7)
- `research_assistant_agent(client)` - Research with progress events
- `task_planner_agent(client)` - Task planning with approvals
### Using Example Agents
@@ -97,7 +97,7 @@ from agent_framework_ag_ui_examples.agents import (
recipe_agent,
)
# Create a chat client (use any ChatClientProtocol implementation)
# Create a chat client (use any SupportsChatGetResponse implementation)
azure_client = AzureOpenAIChatClient(model_id="gpt-4")
openai_client = OpenAIChatClient(model_id="gpt-4o")
@@ -150,16 +150,16 @@ from agent_framework_ag_ui_examples.agents import (
app = FastAPI(title="AG-UI Examples")
# Create a chat client (shared across all agents, or create individual ones)
chat_client = AzureOpenAIChatClient(model_id="gpt-4")
client = AzureOpenAIChatClient(model_id="gpt-4")
# Add all example endpoints
add_agent_framework_fastapi_endpoint(app, simple_agent(chat_client), "/agentic_chat")
add_agent_framework_fastapi_endpoint(app, weather_agent(chat_client), "/backend_tool_rendering")
add_agent_framework_fastapi_endpoint(app, human_in_the_loop_agent(chat_client), "/human_in_the_loop")
add_agent_framework_fastapi_endpoint(app, task_steps_agent_wrapped(chat_client), "/agentic_generative_ui") # type: ignore[arg-type]
add_agent_framework_fastapi_endpoint(app, ui_generator_agent(chat_client), "/tool_based_generative_ui")
add_agent_framework_fastapi_endpoint(app, recipe_agent(chat_client), "/shared_state")
add_agent_framework_fastapi_endpoint(app, document_writer_agent(chat_client), "/predictive_state_updates")
add_agent_framework_fastapi_endpoint(app, simple_agent(client), "/agentic_chat")
add_agent_framework_fastapi_endpoint(app, weather_agent(client), "/backend_tool_rendering")
add_agent_framework_fastapi_endpoint(app, human_in_the_loop_agent(client), "/human_in_the_loop")
add_agent_framework_fastapi_endpoint(app, task_steps_agent_wrapped(client), "/agentic_generative_ui") # type: ignore[arg-type]
add_agent_framework_fastapi_endpoint(app, ui_generator_agent(client), "/tool_based_generative_ui")
add_agent_framework_fastapi_endpoint(app, recipe_agent(client), "/shared_state")
add_agent_framework_fastapi_endpoint(app, document_writer_agent(client), "/predictive_state_updates")
```
## Architecture
@@ -187,8 +187,8 @@ The package uses a clean, orchestrator-based architecture:
You can create your own agent factories following the same pattern as the examples:
```python
from agent_framework import ChatAgent, tool
from agent_framework import ChatClientProtocol
from agent_framework import Agent, tool
from agent_framework import SupportsChatGetResponse
from agent_framework.ag_ui import AgentFrameworkAgent
@tool
@@ -196,19 +196,19 @@ def my_tool(param: str) -> str:
"""My custom tool."""
return f"Result: {param}"
def my_custom_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
def my_custom_agent(client: SupportsChatGetResponse) -> AgentFrameworkAgent:
"""Create a custom agent with the specified chat client.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance
"""
agent = ChatAgent(
agent = Agent(
name="my_custom_agent",
instructions="Custom instructions here",
chat_client=chat_client,
client=client,
tools=[my_tool],
)
@@ -220,8 +220,8 @@ def my_custom_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
# Use it
from agent_framework.azure import AzureOpenAIChatClient
chat_client = AzureOpenAIChatClient()
agent = my_custom_agent(chat_client)
client = AzureOpenAIChatClient()
agent = my_custom_agent(client)
```
### Shared State
@@ -229,14 +229,14 @@ agent = my_custom_agent(chat_client)
State is injected as system messages and updated via predictive state updates:
```python
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.ag_ui import AgentFrameworkAgent
# Create your agent
agent = ChatAgent(
agent = Agent(
name="recipe_agent",
chat_client=AzureOpenAIChatClient(model_id="gpt-4o"),
client=AzureOpenAIChatClient(model_id="gpt-4o"),
)
state_schema = {
@@ -266,14 +266,14 @@ wrapped_agent = AgentFrameworkAgent(
Predictive state updates automatically stream tool arguments as optimistic state updates:
```python
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.ag_ui import AgentFrameworkAgent
# Create your agent
agent = ChatAgent(
agent = Agent(
name="document_writer",
chat_client=AzureOpenAIChatClient(model_id="gpt-4o"),
client=AzureOpenAIChatClient(model_id="gpt-4o"),
)
predict_state_config = {
@@ -4,7 +4,7 @@
from __future__ import annotations
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
from agent_framework.ag_ui import AgentFrameworkAgent
@@ -40,19 +40,19 @@ _DOCUMENT_WRITER_INSTRUCTIONS = (
)
def document_writer_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
def document_writer_agent(client: SupportsChatGetResponse) -> AgentFrameworkAgent:
"""Create a document writer agent with predictive state updates.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance with document writing capabilities
"""
agent = ChatAgent(
agent = Agent(
name="document_writer",
instructions=_DOCUMENT_WRITER_INSTRUCTIONS,
chat_client=chat_client,
client=client,
tools=[write_document],
)
@@ -5,7 +5,7 @@
from enum import Enum
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
from pydantic import BaseModel, Field
@@ -43,16 +43,16 @@ def generate_task_steps(steps: list[TaskStep]) -> str:
return f"Generated {len(steps)} execution steps for the task."
def human_in_the_loop_agent(chat_client: ChatClientProtocol[Any]) -> ChatAgent[Any]:
def human_in_the_loop_agent(client: SupportsChatGetResponse[Any]) -> Agent[Any]:
"""Create a human-in-the-loop agent using tool-based approach for predictive state.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured ChatAgent instance with human-in-the-loop capabilities
A configured Agent instance with human-in-the-loop capabilities
"""
return ChatAgent(
return Agent(
name="human_in_the_loop_agent",
instructions="""You are a helpful assistant that can perform any task by breaking it down into steps.
@@ -81,6 +81,6 @@ def human_in_the_loop_agent(chat_client: ChatClientProtocol[Any]) -> ChatAgent[A
After the user approves and the function executes, THEN provide a brief acknowledgment like:
"The plan has been created with X steps selected."
""",
chat_client=chat_client,
client=client,
tools=[generate_task_steps],
)
@@ -7,7 +7,7 @@ from __future__ import annotations
from enum import Enum
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
from agent_framework.ag_ui import AgentFrameworkAgent
from pydantic import BaseModel, Field
@@ -104,19 +104,19 @@ _RECIPE_INSTRUCTIONS = """You are a helpful recipe assistant that creates and mo
"""
def recipe_agent(chat_client: ChatClientProtocol[Any]) -> AgentFrameworkAgent:
def recipe_agent(client: SupportsChatGetResponse[Any]) -> AgentFrameworkAgent:
"""Create a recipe agent with streaming state updates.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance with recipe management
"""
agent = ChatAgent(
agent = Agent(
name="recipe_agent",
instructions=_RECIPE_INSTRUCTIONS,
chat_client=chat_client,
client=client,
tools=[update_recipe],
)
@@ -5,7 +5,7 @@
import asyncio
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
from agent_framework.ag_ui import AgentFrameworkAgent
@@ -88,19 +88,19 @@ _RESEARCH_ASSISTANT_INSTRUCTIONS = (
)
def research_assistant_agent(chat_client: ChatClientProtocol[Any]) -> AgentFrameworkAgent:
def research_assistant_agent(client: SupportsChatGetResponse[Any]) -> AgentFrameworkAgent:
"""Create a research assistant agent.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance with research capabilities
"""
agent = ChatAgent(
agent = Agent(
name="research_assistant",
instructions=_RESEARCH_ASSISTANT_INSTRUCTIONS,
chat_client=chat_client,
client=client,
tools=[research_topic, create_presentation, analyze_data],
)
@@ -4,20 +4,20 @@
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol
from agent_framework import Agent, SupportsChatGetResponse
def simple_agent(chat_client: ChatClientProtocol[Any]) -> ChatAgent[Any]:
def simple_agent(client: SupportsChatGetResponse[Any]) -> Agent[Any]:
"""Create a simple chat agent.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured ChatAgent instance
A configured Agent instance
"""
return ChatAgent[Any](
return Agent[Any](
name="simple_chat_agent",
instructions="You are a helpful assistant. Be concise and friendly.",
chat_client=chat_client,
client=client,
)
@@ -4,7 +4,7 @@
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
from agent_framework.ag_ui import AgentFrameworkAgent
@@ -61,19 +61,19 @@ _TASK_PLANNER_INSTRUCTIONS = (
)
def task_planner_agent(chat_client: ChatClientProtocol[Any]) -> AgentFrameworkAgent:
def task_planner_agent(client: SupportsChatGetResponse[Any]) -> AgentFrameworkAgent:
"""Create a task planner agent with user approval for actions.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance with task planning capabilities
"""
agent = ChatAgent(
agent = Agent(
name="task_planner",
instructions=_TASK_PLANNER_INSTRUCTIONS,
chat_client=chat_client,
client=client,
tools=[create_calendar_event, send_email, book_meeting_room],
)
@@ -20,7 +20,7 @@ from ag_ui.core import (
TextMessageStartEvent,
ToolCallStartEvent,
)
from agent_framework import ChatAgent, ChatClientProtocol, ChatMessage, Content, tool
from agent_framework import Agent, Content, Message, SupportsChatGetResponse, tool
from agent_framework.ag_ui import AgentFrameworkAgent
from pydantic import BaseModel, Field
@@ -54,16 +54,16 @@ def generate_task_steps(steps: list[TaskStep]) -> str:
return "Steps generated."
def _create_task_steps_agent(chat_client: ChatClientProtocol[Any]) -> AgentFrameworkAgent:
def _create_task_steps_agent(client: SupportsChatGetResponse[Any]) -> AgentFrameworkAgent:
"""Create the task steps agent using tool-based approach for streaming.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance
"""
agent = ChatAgent[Any](
agent = Agent[Any](
name="task_steps_agent",
instructions="""You are a helpful assistant that breaks down tasks into actionable steps.
@@ -83,7 +83,7 @@ def _create_task_steps_agent(chat_client: ChatClientProtocol[Any]) -> AgentFrame
- "Installing platform"
- "Adding finishing touches"
""",
chat_client=chat_client,
client=client,
tools=[generate_task_steps],
)
@@ -220,30 +220,30 @@ class TaskStepsAgentWithExecution:
# Get the underlying chat agent and client
chat_agent = self._base_agent.agent # type: ignore
chat_client = chat_agent.chat_client # type: ignore
client = chat_agent.client # type: ignore
# Build messages for summary call
original_messages = input_data.get("messages", [])
# Convert to ChatMessage objects if needed
messages: list[ChatMessage] = []
# Convert to Message objects if needed
messages: list[Message] = []
for msg in original_messages:
if isinstance(msg, dict):
content_str = msg.get("content", "")
if isinstance(content_str, str):
messages.append(
ChatMessage(
Message(
role=msg.get("role", "user"),
contents=[Content.from_text(text=content_str)],
)
)
elif isinstance(msg, ChatMessage):
elif isinstance(msg, Message):
messages.append(msg)
# Add completion message
messages.append(
ChatMessage(
Message(
role="user",
contents=[
Content.from_text(
@@ -270,7 +270,7 @@ class TaskStepsAgentWithExecution:
# Stream completion
accumulated_text = ""
async for chunk in chat_client.get_response(messages=messages, stream=True):
async for chunk in client.get_response(messages=messages, stream=True):
# chunk is ChatResponseUpdate
if hasattr(chunk, "text") and chunk.text:
accumulated_text += chunk.text
@@ -332,14 +332,14 @@ class TaskStepsAgentWithExecution:
yield run_finished_event
def task_steps_agent_wrapped(chat_client: ChatClientProtocol[Any]) -> TaskStepsAgentWithExecution:
def task_steps_agent_wrapped(client: SupportsChatGetResponse[Any]) -> TaskStepsAgentWithExecution:
"""Create a task steps agent with execution simulation.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A wrapped agent instance with step execution simulation
"""
base_agent = _create_task_steps_agent(chat_client)
base_agent = _create_task_steps_agent(client)
return TaskStepsAgentWithExecution(base_agent)
@@ -7,7 +7,7 @@ from __future__ import annotations
import sys
from typing import TYPE_CHECKING, Any, TypedDict
from agent_framework import ChatAgent, ChatClientProtocol, FunctionTool
from agent_framework import Agent, FunctionTool, SupportsChatGetResponse
from agent_framework.ag_ui import AgentFrameworkAgent
if sys.version_info >= (3, 13):
@@ -168,19 +168,19 @@ _UI_GENERATOR_INSTRUCTIONS = """You MUST use the provided tools to generate cont
OptionsT = TypeVar("OptionsT", bound=TypedDict, default="ChatOptions") # type: ignore[valid-type]
def ui_generator_agent(chat_client: ChatClientProtocol[OptionsT]) -> AgentFrameworkAgent:
def ui_generator_agent(client: SupportsChatGetResponse[OptionsT]) -> AgentFrameworkAgent:
"""Create a UI generator agent with custom React component rendering.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured AgentFrameworkAgent instance with UI generation capabilities
"""
agent = ChatAgent(
agent = Agent(
name="ui_generator",
instructions=_UI_GENERATOR_INSTRUCTIONS,
chat_client=chat_client,
client=client,
tools=[generate_haiku, create_chart, display_timeline, show_comparison_table],
# Force tool usage - the LLM MUST call a tool, cannot respond with plain text
default_options={"tool_choice": "required"}, # type: ignore
@@ -6,7 +6,7 @@ from __future__ import annotations
from typing import Any
from agent_framework import ChatAgent, ChatClientProtocol, tool
from agent_framework import Agent, SupportsChatGetResponse, tool
@tool
@@ -59,16 +59,16 @@ def get_forecast(location: str, days: int = 3) -> str:
return f"{days}-day forecast for {location}:\n" + "\n".join(forecast)
def weather_agent(chat_client: ChatClientProtocol[Any]) -> ChatAgent[Any]:
def weather_agent(client: SupportsChatGetResponse[Any]) -> Agent[Any]:
"""Create a weather agent with get_weather and get_forecast tools.
Args:
chat_client: The chat client to use for the agent
client: The chat client to use for the agent
Returns:
A configured ChatAgent instance with weather tools
A configured Agent instance with weather tools
"""
return ChatAgent[Any](
return Agent[Any](
name="weather_agent",
instructions=(
"You are a helpful weather assistant. "
@@ -76,6 +76,6 @@ def weather_agent(chat_client: ChatClientProtocol[Any]) -> ChatAgent[Any]:
"Always provide friendly and informative responses. "
"First return the weather result, and then return details about the forecast."
),
chat_client=chat_client,
client=client,
tools=[get_weather, get_forecast],
)
@@ -4,7 +4,7 @@
from typing import Any, cast
from agent_framework._clients import ChatClientProtocol
from agent_framework._clients import SupportsChatGetResponse
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from agent_framework.azure import AzureOpenAIChatClient
from fastapi import FastAPI
@@ -19,10 +19,10 @@ def register_backend_tool_rendering(app: FastAPI) -> None:
app: The FastAPI application.
"""
# Create a chat client and call the factory function
chat_client = cast(ChatClientProtocol[Any], AzureOpenAIChatClient())
client = cast(SupportsChatGetResponse[Any], AzureOpenAIChatClient())
add_agent_framework_fastapi_endpoint(
app,
weather_agent(chat_client),
weather_agent(client),
"/backend_tool_rendering",
)
@@ -10,7 +10,7 @@ from typing import cast
import uvicorn
from agent_framework import ChatOptions
from agent_framework._clients import ChatClientProtocol
from agent_framework._clients import SupportsChatGetResponse
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from agent_framework.anthropic import AnthropicClient
from agent_framework.azure import AzureOpenAIChatClient
@@ -67,43 +67,43 @@ app.add_middleware(
# Create a shared chat client for all agents
# You can use different chat clients for different agents if needed
# Set CHAT_CLIENT=anthropic to use Anthropic, defaults to Azure OpenAI
chat_client: ChatClientProtocol[ChatOptions] = cast(
ChatClientProtocol[ChatOptions],
client: SupportsChatGetResponse[ChatOptions] = cast(
SupportsChatGetResponse[ChatOptions],
AnthropicClient() if os.getenv("CHAT_CLIENT", "").lower() == "anthropic" else AzureOpenAIChatClient(),
)
# Agentic Chat - basic chat agent
add_agent_framework_fastapi_endpoint(
app=app,
agent=simple_agent(chat_client),
agent=simple_agent(client),
path="/agentic_chat",
)
# Backend Tool Rendering - agent with tools
add_agent_framework_fastapi_endpoint(
app=app,
agent=weather_agent(chat_client),
agent=weather_agent(client),
path="/backend_tool_rendering",
)
# Shared State - recipe agent with structured output
add_agent_framework_fastapi_endpoint(
app=app,
agent=recipe_agent(chat_client),
agent=recipe_agent(client),
path="/shared_state",
)
# Predictive State Updates - document writer with predictive state
add_agent_framework_fastapi_endpoint(
app=app,
agent=document_writer_agent(chat_client),
agent=document_writer_agent(client),
path="/predictive_state_updates",
)
# Human in the Loop - human-in-the-loop agent with step customization
add_agent_framework_fastapi_endpoint(
app=app,
agent=human_in_the_loop_agent(chat_client),
agent=human_in_the_loop_agent(client),
path="/human_in_the_loop",
state_schema={"steps": {"type": "array"}},
predict_state_config={"steps": {"tool": "generate_task_steps", "tool_argument": "steps"}},
@@ -112,14 +112,14 @@ add_agent_framework_fastapi_endpoint(
# Agentic Generative UI - task steps agent with streaming state updates
add_agent_framework_fastapi_endpoint(
app=app,
agent=task_steps_agent_wrapped(chat_client), # type: ignore[arg-type]
agent=task_steps_agent_wrapped(client), # type: ignore[arg-type]
path="/agentic_generative_ui",
)
# Tool-based Generative UI - UI generator with frontend-rendered tools
add_agent_framework_fastapi_endpoint(
app=app,
agent=ui_generator_agent(chat_client),
agent=ui_generator_agent(client),
path="/tool_based_generative_ui",
)
+14 -14
View File
@@ -35,9 +35,9 @@ python client_advanced.py
**Note:** This example shows direct `AGUIChatClient` usage. Tool execution and conversation continuity depend on server-side configuration and capabilities.
### ChatAgent Integration (`client_with_agent.py`)
### Agent Integration (`client_with_agent.py`)
Best practice example using `ChatAgent` wrapper with **AgentThread**
Best practice example using `Agent` wrapper with **AgentThread**
- **AgentThread** maintains conversation state
- Client-side conversation history management via `thread.message_store`
- **Hybrid tool execution**: client-side + server-side tools simultaneously
@@ -77,7 +77,7 @@ The AG-UI protocol supports two approaches to conversation history:
- Full message history sent with each request
- Works with any AG-UI server (stateful or stateless)
The `ChatAgent` wrapper (used in client_with_agent.py) collects messages from local storage and sends the full history to `AGUIChatClient`, which then forwards everything to the server.
The `Agent` wrapper (used in client_with_agent.py) collects messages from local storage and sends the full history to `AGUIChatClient`, which then forwards everything to the server.
### Tool/Function Calling
@@ -91,14 +91,14 @@ Client defines: Server defines:
User: "What's the weather in SF and what time is it?"
ChatAgent sends: full history + tool definitions for get_weather, read_sensors
Agent sends: full history + tool definitions for get_weather, read_sensors
Server LLM decides: "I need get_weather('SF') and get_current_time()"
Server executes get_current_time() → "2025-11-11 14:30:00 UTC"
Server sends function call request → get_weather('SF')
ChatAgent intercepts get_weather call → executes locally
Agent intercepts get_weather call → executes locally
Client sends result → "Sunny, 72°F"
@@ -110,7 +110,7 @@ Client receives final response
**How it works:**
1. **Client-Side Tools** (`client_with_agent.py`):
- Tools defined in ChatAgent's `tools` parameter execute locally
- Tools defined in Agent's `tools` parameter execute locally
- Tool metadata (name, description, schema) sent to server for planning
- When server requests client tool → client intercepts → executes locally → sends result
@@ -126,7 +126,7 @@ Client receives final response
- Client tools execute client-side
**Direct AGUIChatClient Usage** (client_advanced.py):
Even without ChatAgent wrapper, client-side tools work:
Even without Agent wrapper, client-side tools work:
- Tools passed in ChatOptions execute locally
- Server can also have its own tools
- Hybrid execution works automatically
@@ -184,7 +184,7 @@ Create a file named `server.py`:
import os
from agent_framework import ChatAgent
from agent_framework import Agent
from agent_framework.azure import AzureOpenAIChatClient
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from fastapi import FastAPI
@@ -202,10 +202,10 @@ if not api_key:
raise ValueError("AZURE_OPENAI_API_KEY environment variable is required")
# Create the AI agent
agent = ChatAgent(
agent = Agent(
name="AGUIAssistant",
instructions="You are a helpful assistant.",
chat_client=AzureOpenAIChatClient(
client=AzureOpenAIChatClient(
endpoint=endpoint,
deployment_name=deployment_name,
api_key=api_key,
@@ -227,7 +227,7 @@ if __name__ == "__main__":
### Key Concepts
- **`add_agent_framework_fastapi_endpoint`**: Registers the AG-UI endpoint with automatic request/response handling and SSE streaming
- **`ChatAgent`**: The agent that will handle incoming requests
- **`Agent`**: The agent that will handle incoming requests
- **FastAPI Integration**: Uses FastAPI's native async support for streaming responses
- **Instructions**: The agent is created with default instructions, which can be overridden by client messages
- **Configuration**: `AzureOpenAIChatClient` can read from environment variables (`AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_CHAT_DEPLOYMENT_NAME`, `AZURE_OPENAI_API_KEY`) or accept parameters directly
@@ -236,10 +236,10 @@ if __name__ == "__main__":
```python
# No need to read environment variables manually
agent = ChatAgent(
agent = Agent(
name="AGUIAssistant",
instructions="You are a helpful assistant.",
chat_client=AzureOpenAIChatClient(), # Reads from environment automatically
client=AzureOpenAIChatClient(), # Reads from environment automatically
)
```
@@ -354,7 +354,7 @@ if __name__ == "__main__":
- **Thread Management**: Pass `thread_id` in metadata to maintain conversation context across requests
- **Streaming Responses**: Use `get_response(..., stream=True)` for real-time streaming or `get_response(..., stream=False)` for non-streaming
- **Context Manager**: Use `async with` for automatic cleanup of HTTP connections
- **Standard Interface**: Works with all Agent Framework patterns (ChatAgent, tools, etc.)
- **Standard Interface**: Works with all Agent Framework patterns (Agent, tools, etc.)
- **Hybrid Tool Execution**: Supports both client-side and server-side tools executing together in the same conversation
### Configure and Run the Client
@@ -114,15 +114,15 @@ async def non_streaming_example(client: AGUIChatClient, thread_id: str | None =
async def tool_example(client: AGUIChatClient, thread_id: str | None = None):
"""Demonstrate sending tool definitions to the server.
IMPORTANT: When using AGUIChatClient directly (without ChatAgent wrapper):
IMPORTANT: When using AGUIChatClient directly (without Agent wrapper):
- Tools are sent as DEFINITIONS only
- No automatic client-side execution (no function invocation middleware)
- Server must have matching tool implementations to execute them
For CLIENT-SIDE tool execution (like .NET AGUIClient sample):
- Use ChatAgent wrapper with tools
- Use Agent wrapper with tools
- See client_with_agent.py for the hybrid pattern
- ChatAgent middleware intercepts and executes client tools locally
- Agent middleware intercepts and executes client tools locally
- Server can have its own tools that execute server-side
- Both client and server tools work together in same conversation
@@ -186,7 +186,7 @@ async def conversation_example(client: AGUIChatClient):
# Check if context was maintained
if "alice" not in response2.text.lower():
print("\n[Note: Server may not maintain thread context - consider using ChatAgent for history management]")
print("\n[Note: Server may not maintain thread context - consider using Agent for history management]")
# Third turn
print("\nUser: Can you also tell me what 10 * 5 is?\n")
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.
"""Example showing ChatAgent with AGUIChatClient for hybrid tool execution.
"""Example showing Agent with AGUIChatClient for hybrid tool execution.
This demonstrates the HYBRID pattern matching .NET AGUIClient implementation:
@@ -24,7 +24,7 @@ import asyncio
import logging
import os
from agent_framework import ChatAgent, tool
from agent_framework import Agent, tool
from agent_framework.ag_ui import AGUIChatClient
# Enable debug logging
@@ -55,7 +55,7 @@ def get_weather(location: str) -> str:
async def main():
"""Demonstrate ChatAgent + AGUIChatClient hybrid tool execution.
"""Demonstrate Agent + AGUIChatClient hybrid tool execution.
This matches the .NET pattern from Program.cs where:
- AIAgent agent = chatClient.CreateAIAgent(tools: [...])
@@ -63,14 +63,14 @@ async def main():
- RunStreamingAsync(messages, thread)
Python equivalent:
- agent = ChatAgent(chat_client=AGUIChatClient(...), tools=[...])
- agent = Agent(client=AGUIChatClient(...), tools=[...])
- thread = agent.get_new_thread() # Creates thread with message_store
- agent.run(message, stream=True, thread=thread) # Thread accumulates history
"""
server_url = os.environ.get("AGUI_SERVER_URL", "http://127.0.0.1:5100/")
print("=" * 70)
print("ChatAgent + AGUIChatClient: Hybrid Tool Execution")
print("Agent + AGUIChatClient: Hybrid Tool Execution")
print("=" * 70)
print(f"\nServer: {server_url}")
print("\nThis example demonstrates:")
@@ -82,11 +82,11 @@ async def main():
try:
# Create remote client in async context manager
async with AGUIChatClient(endpoint=server_url) as remote_client:
# Wrap in ChatAgent for conversation history management
agent = ChatAgent(
# Wrap in Agent for conversation history management
agent = Agent(
name="remote_assistant",
instructions="You are a helpful assistant. Remember user information across the conversation.",
chat_client=remote_client,
client=remote_client,
tools=[get_weather],
)
@@ -7,7 +7,7 @@ from __future__ import annotations
import logging
import os
from agent_framework import ChatAgent, tool
from agent_framework import Agent, tool
from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
from agent_framework.azure import AzureOpenAIChatClient
from dotenv import load_dotenv
@@ -116,10 +116,10 @@ def get_time_zone(location: str) -> str:
# The client will send get_weather tool metadata so the LLM knows about it,
# and the function invocation mixin on AGUIChatClient will execute it client-side.
# This matches the .NET AG-UI hybrid execution pattern.
agent = ChatAgent(
agent = Agent(
name="AGUIAssistant",
instructions="You are a helpful assistant. Use get_weather for weather and get_time_zone for time zones.",
chat_client=AzureOpenAIChatClient(
client=AzureOpenAIChatClient(
endpoint=endpoint,
deployment_name=deployment_name,
),
+2 -2
View File
@@ -1,6 +1,6 @@
[project]
name = "agent-framework-ag-ui"
version = "1.0.0b260130"
version = "1.0.0b260210"
description = "AG-UI protocol integration for Agent Framework"
readme = "README.md"
license-files = ["LICENSE"]
@@ -22,7 +22,7 @@ classifiers = [
"Typing :: Typed",
]
dependencies = [
"agent-framework-core>=1.0.0b260130",
"agent-framework-core>=1.0.0b260210",
"ag-ui-protocol>=0.1.9",
"fastapi>=0.115.0",
"uvicorn>=0.30.0"
+17 -17
View File
@@ -13,13 +13,13 @@ from agent_framework import (
AgentResponseUpdate,
AgentThread,
BaseChatClient,
ChatClientProtocol,
ChatMessage,
ChatOptions,
ChatResponse,
ChatResponseUpdate,
Content,
Message,
SupportsAgentRun,
SupportsChatGetResponse,
)
from agent_framework._clients import OptionsCoT
from agent_framework._middleware import ChatMiddlewareLayer
@@ -43,7 +43,7 @@ class StreamingChatClientStub(
BaseChatClient[OptionsCoT],
Generic[OptionsCoT],
):
"""Typed streaming stub that satisfies ChatClientProtocol."""
"""Typed streaming stub that satisfies SupportsChatGetResponse."""
def __init__(self, stream_fn: StreamFn, response_fn: ResponseFn | None = None) -> None:
super().__init__(function_middleware=[])
@@ -55,7 +55,7 @@ class StreamingChatClientStub(
@overload
def get_response(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage],
messages: str | Message | Sequence[str | Message],
*,
stream: Literal[False] = ...,
options: ChatOptions[Any],
@@ -65,7 +65,7 @@ class StreamingChatClientStub(
@overload
def get_response(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage],
messages: str | Message | Sequence[str | Message],
*,
stream: Literal[False] = ...,
options: OptionsCoT | ChatOptions[None] | None = ...,
@@ -75,7 +75,7 @@ class StreamingChatClientStub(
@overload
def get_response(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage],
messages: str | Message | Sequence[str | Message],
*,
stream: Literal[True],
options: OptionsCoT | ChatOptions[Any] | None = ...,
@@ -84,7 +84,7 @@ class StreamingChatClientStub(
def get_response(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage],
messages: str | Message | Sequence[str | Message],
*,
stream: bool = False,
options: OptionsCoT | ChatOptions[Any] | None = None,
@@ -106,7 +106,7 @@ class StreamingChatClientStub(
def _inner_get_response(
self,
*,
messages: Sequence[ChatMessage],
messages: Sequence[Message],
stream: bool = False,
options: Mapping[str, Any],
**kwargs: Any,
@@ -121,7 +121,7 @@ class StreamingChatClientStub(
return self._get_response_impl(messages, options, **kwargs)
async def _get_response_impl(
self, messages: Sequence[ChatMessage], options: Mapping[str, Any], **kwargs: Any
self, messages: Sequence[Message], options: Mapping[str, Any], **kwargs: Any
) -> ChatResponse:
"""Non-streaming implementation."""
if self._response_fn is not None:
@@ -132,7 +132,7 @@ class StreamingChatClientStub(
contents.extend(update.contents)
return ChatResponse(
messages=[ChatMessage(role="assistant", contents=contents)],
messages=[Message(role="assistant", contents=contents)],
response_id="stub-response",
)
@@ -141,7 +141,7 @@ def stream_from_updates(updates: list[ChatResponseUpdate]) -> StreamFn:
"""Create a stream function that yields from a static list of updates."""
async def _stream(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
for update in updates:
yield update
@@ -159,7 +159,7 @@ class StubAgent(SupportsAgentRun):
agent_id: str = "stub-agent",
agent_name: str | None = "stub-agent",
default_options: Any | None = None,
chat_client: Any | None = None,
client: Any | None = None,
) -> None:
self.id = agent_id
self.name = agent_name
@@ -168,14 +168,14 @@ class StubAgent(SupportsAgentRun):
self.default_options: dict[str, Any] = (
default_options if isinstance(default_options, dict) else {"tools": None, "response_format": None}
)
self.chat_client = chat_client or SimpleNamespace(function_invocation_configuration=None)
self.client = client or SimpleNamespace(function_invocation_configuration=None)
self.messages_received: list[Any] = []
self.tools_received: list[Any] | None = None
@overload
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: Literal[False] = ...,
thread: AgentThread | None = None,
@@ -185,7 +185,7 @@ class StubAgent(SupportsAgentRun):
@overload
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: Literal[True],
thread: AgentThread | None = None,
@@ -194,7 +194,7 @@ class StubAgent(SupportsAgentRun):
def run(
self,
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
messages: str | Message | Sequence[str | Message] | None = None,
*,
stream: bool = False,
thread: AgentThread | None = None,
@@ -226,7 +226,7 @@ class StubAgent(SupportsAgentRun):
@pytest.fixture
def streaming_chat_client_stub() -> type[ChatClientProtocol]:
def streaming_chat_client_stub() -> type[SupportsChatGetResponse]:
"""Return the StreamingChatClientStub class for creating test instances."""
return StreamingChatClientStub # type: ignore[return-value]
@@ -7,11 +7,11 @@ from collections.abc import AsyncGenerator, Awaitable, MutableSequence
from typing import Any
from agent_framework import (
ChatMessage,
ChatOptions,
ChatResponse,
ChatResponseUpdate,
Content,
Message,
ResponseStream,
tool,
)
@@ -29,13 +29,11 @@ class TestableAGUIChatClient(AGUIChatClient):
"""Expose http service for monkeypatching."""
return self._http_service
def extract_state_from_messages(
self, messages: list[ChatMessage]
) -> tuple[list[ChatMessage], dict[str, Any] | None]:
def extract_state_from_messages(self, messages: list[Message]) -> tuple[list[Message], dict[str, Any] | None]:
"""Expose state extraction helper."""
return self._extract_state_from_messages(messages)
def convert_messages_to_agui_format(self, messages: list[ChatMessage]) -> list[dict[str, Any]]:
def convert_messages_to_agui_format(self, messages: list[Message]) -> list[dict[str, Any]]:
"""Expose message conversion helper."""
return self._convert_messages_to_agui_format(messages)
@@ -44,7 +42,7 @@ class TestableAGUIChatClient(AGUIChatClient):
return self._get_thread_id(options)
def inner_get_response(
self, *, messages: MutableSequence[ChatMessage], options: dict[str, Any], stream: bool = False
self, *, messages: MutableSequence[Message], options: dict[str, Any], stream: bool = False
) -> Awaitable[ChatResponse] | ResponseStream[ChatResponseUpdate, ChatResponse]:
"""Proxy to protected response call."""
return self._inner_get_response(messages=messages, options=options, stream=stream)
@@ -69,8 +67,8 @@ class TestAGUIChatClient:
"""Test state extraction when no state is present."""
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
messages = [
ChatMessage(role="user", text="Hello"),
ChatMessage(role="assistant", text="Hi there"),
Message(role="user", text="Hello"),
Message(role="assistant", text="Hi there"),
]
result_messages, state = client.extract_state_from_messages(messages)
@@ -89,8 +87,8 @@ class TestAGUIChatClient:
state_b64 = base64.b64encode(state_json.encode("utf-8")).decode("utf-8")
messages = [
ChatMessage(role="user", text="Hello"),
ChatMessage(
Message(role="user", text="Hello"),
Message(
role="user",
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
),
@@ -112,7 +110,7 @@ class TestAGUIChatClient:
state_b64 = base64.b64encode(invalid_json.encode("utf-8")).decode("utf-8")
messages = [
ChatMessage(
Message(
role="user",
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
),
@@ -127,8 +125,8 @@ class TestAGUIChatClient:
"""Test message conversion to AG-UI format."""
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
messages = [
ChatMessage(role="user", text="What is the weather?"),
ChatMessage(role="assistant", text="Let me check.", message_id="msg_123"),
Message(role="user", text="What is the weather?"),
Message(role="assistant", text="Let me check.", message_id="msg_123"),
]
agui_messages = client.convert_messages_to_agui_format(messages)
@@ -175,7 +173,7 @@ class TestAGUIChatClient:
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
messages = [ChatMessage(role="user", text="Test message")]
messages = [Message(role="user", text="Test message")]
chat_options = ChatOptions()
updates: list[ChatResponseUpdate] = []
@@ -208,7 +206,7 @@ class TestAGUIChatClient:
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
messages = [ChatMessage(role="user", text="Test message")]
messages = [Message(role="user", text="Test message")]
chat_options = {}
response = await client.inner_get_response(messages=messages, options=chat_options)
@@ -251,7 +249,7 @@ class TestAGUIChatClient:
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
messages = [ChatMessage(role="user", text="Test with tools")]
messages = [Message(role="user", text="Test with tools")]
chat_options = ChatOptions(tools=[test_tool])
response = await client.inner_get_response(messages=messages, options=chat_options)
@@ -275,7 +273,7 @@ class TestAGUIChatClient:
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
messages = [ChatMessage(role="user", text="Test server tool execution")]
messages = [Message(role="user", text="Test server tool execution")]
updates: list[ChatResponseUpdate] = []
async for update in client.get_response(messages, stream=True):
@@ -317,7 +315,7 @@ class TestAGUIChatClient:
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
messages = [ChatMessage(role="user", text="Test server tool execution")]
messages = [Message(role="user", text="Test server tool execution")]
async for _ in client.get_response(
messages, stream=True, options={"tool_choice": "auto", "tools": [client_tool]}
@@ -333,8 +331,8 @@ class TestAGUIChatClient:
state_b64 = base64.b64encode(state_json.encode("utf-8")).decode("utf-8")
messages = [
ChatMessage(role="user", text="Hello"),
ChatMessage(
Message(role="user", text="Hello"),
Message(
role="user",
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
),
@@ -7,7 +7,7 @@ from collections.abc import AsyncIterator, MutableSequence
from typing import Any
import pytest
from agent_framework import ChatAgent, ChatMessage, ChatOptions, ChatResponseUpdate, Content
from agent_framework import Agent, ChatOptions, ChatResponseUpdate, Content, Message
from pydantic import BaseModel
@@ -16,12 +16,12 @@ async def test_agent_initialization_basic(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent[ChatOptions](
chat_client=streaming_chat_client_stub(stream_fn),
agent = Agent[ChatOptions](
client=streaming_chat_client_stub(stream_fn),
name="test_agent",
instructions="Test",
)
@@ -38,11 +38,11 @@ async def test_agent_initialization_with_state_schema(streaming_chat_client_stub
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
state_schema: dict[str, dict[str, Any]] = {"document": {"type": "string"}}
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
@@ -54,11 +54,11 @@ async def test_agent_initialization_with_predict_state_config(streaming_chat_cli
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
predict_config = {"document": {"tool": "write_doc", "tool_argument": "content"}}
wrapper = AgentFrameworkAgent(agent=agent, predict_state_config=predict_config)
@@ -70,7 +70,7 @@ async def test_agent_initialization_with_pydantic_state_schema(streaming_chat_cl
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
@@ -78,7 +78,7 @@ async def test_agent_initialization_with_pydantic_state_schema(streaming_chat_cl
document: str
tags: list[str] = []
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper_class_schema = AgentFrameworkAgent(agent=agent, state_schema=MyState)
wrapper_instance_schema = AgentFrameworkAgent(agent=agent, state_schema=MyState(document="hi"))
@@ -93,11 +93,11 @@ async def test_run_started_event_emission(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data = {"messages": [{"role": "user", "content": "Hi"}]}
@@ -117,11 +117,11 @@ async def test_predict_state_custom_event_emission(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
predict_config = {
"document": {"tool": "write_doc", "tool_argument": "content"},
"summary": {"tool": "summarize", "tool_argument": "text"},
@@ -149,11 +149,11 @@ async def test_initial_state_snapshot_with_schema(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
state_schema = {"document": {"type": "string"}}
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
@@ -179,11 +179,11 @@ async def test_state_initialization_object_type(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
state_schema: dict[str, dict[str, Any]] = {"recipe": {"type": "object", "properties": {}}}
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
@@ -206,11 +206,11 @@ async def test_state_initialization_array_type(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
state_schema: dict[str, dict[str, Any]] = {"steps": {"type": "array", "items": {}}}
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
@@ -233,11 +233,11 @@ async def test_run_finished_event_emission(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data = {"messages": [{"role": "user", "content": "Hi"}]}
@@ -255,11 +255,11 @@ async def test_tool_result_confirm_changes_accepted(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Document updated")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(
agent=agent,
state_schema={"document": {"type": "string"}},
@@ -302,11 +302,11 @@ async def test_tool_result_confirm_changes_rejected(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
# Simulate tool result message with rejection
@@ -336,11 +336,11 @@ async def test_tool_result_function_approval_accepted(streaming_chat_client_stub
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
# Simulate tool result with multiple steps
@@ -382,11 +382,11 @@ async def test_tool_result_function_approval_rejected(streaming_chat_client_stub
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
# Simulate tool result rejection with steps
@@ -425,13 +425,13 @@ async def test_thread_metadata_tracking(streaming_chat_client_stub):
captured_options: dict[str, Any] = {}
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
# Capture options to verify internal keys are NOT passed to chat client
captured_options.update(options)
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data = {
@@ -445,7 +445,7 @@ async def test_thread_metadata_tracking(streaming_chat_client_stub):
events.append(event)
# AG-UI internal metadata should be stored in thread.metadata
thread = agent.chat_client.last_thread
thread = agent.client.last_thread
thread_metadata = thread.metadata if thread and hasattr(thread, "metadata") else {}
assert thread_metadata.get("ag_ui_thread_id") == "test_thread_123"
assert thread_metadata.get("ag_ui_run_id") == "test_run_456"
@@ -467,13 +467,13 @@ async def test_state_context_injection(streaming_chat_client_stub):
captured_options: dict[str, Any] = {}
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
# Capture options to verify internal keys are NOT passed to chat client
captured_options.update(options)
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(
agent=agent,
state_schema={"document": {"type": "string"}},
@@ -489,7 +489,7 @@ async def test_state_context_injection(streaming_chat_client_stub):
events.append(event)
# Current state should be stored in thread.metadata
thread = agent.chat_client.last_thread
thread = agent.client.last_thread
thread_metadata = thread.metadata if thread and hasattr(thread, "metadata") else {}
current_state = thread_metadata.get("current_state")
if isinstance(current_state, str):
@@ -506,11 +506,11 @@ async def test_no_messages_provided(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data: dict[str, Any] = {"messages": []}
@@ -530,11 +530,11 @@ async def test_message_end_event_emission(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello world")])
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data: dict[str, Any] = {"messages": [{"role": "user", "content": "Hi"}]}
@@ -558,13 +558,13 @@ async def test_error_handling_with_exception(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
if False:
yield ChatResponseUpdate(contents=[])
raise RuntimeError("Simulated failure")
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
input_data: dict[str, Any] = {"messages": [{"role": "user", "content": "Hi"}]}
@@ -579,13 +579,13 @@ async def test_json_decode_error_in_tool_result(streaming_chat_client_stub):
from agent_framework.ag_ui import AgentFrameworkAgent
async def stream_fn(
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
if False:
yield ChatResponseUpdate(contents=[])
raise AssertionError("ChatClient should not be called with orphaned tool result")
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent)
# Send invalid JSON as tool result without preceding tool call
@@ -618,13 +618,13 @@ async def test_agent_with_use_service_thread_is_false(streaming_chat_client_stub
request_service_thread_id: str | None = None
async def stream_fn(
messages: MutableSequence[ChatMessage], chat_options: ChatOptions, **kwargs: Any
messages: MutableSequence[Message], chat_options: ChatOptions, **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
yield ChatResponseUpdate(
contents=[Content.from_text(text="Response")], response_id="resp_67890", conversation_id="conv_12345"
)
agent = ChatAgent(chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent, use_service_thread=False)
input_data = {"messages": [{"role": "user", "content": "Hi"}], "thread_id": "conv_123456"}
@@ -642,7 +642,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
request_service_thread_id: str | None = None
async def stream_fn(
messages: MutableSequence[ChatMessage], chat_options: ChatOptions, **kwargs: Any
messages: MutableSequence[Message], chat_options: ChatOptions, **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
nonlocal request_service_thread_id
thread = kwargs.get("thread")
@@ -651,7 +651,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
contents=[Content.from_text(text="Response")], response_id="resp_67890", conversation_id="conv_12345"
)
agent = ChatAgent(chat_client=streaming_chat_client_stub(stream_fn))
agent = Agent(client=streaming_chat_client_stub(stream_fn))
wrapper = AgentFrameworkAgent(agent=agent, use_service_thread=True)
input_data = {"messages": [{"role": "user", "content": "Hi"}], "thread_id": "conv_123456"}
@@ -659,7 +659,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
events: list[Any] = []
async for event in wrapper.run_agent(input_data):
events.append(event)
request_service_thread_id = agent.chat_client.last_service_thread_id
request_service_thread_id = agent.client.last_service_thread_id
assert request_service_thread_id == "conv_123456" # type: ignore[attr-defined] (service_thread_id should be set)
@@ -679,15 +679,15 @@ async def test_function_approval_mode_executes_tool(streaming_chat_client_stub):
return "2025/12/01 12:00:00"
async def stream_fn(
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
# Capture the messages received by the chat client
messages_received.clear()
messages_received.extend(messages)
yield ChatResponseUpdate(contents=[Content.from_text(text="Processing completed")])
agent = ChatAgent(
chat_client=streaming_chat_client_stub(stream_fn),
agent = Agent(
client=streaming_chat_client_stub(stream_fn),
name="test_agent",
instructions="Test",
tools=[get_datetime],
@@ -770,17 +770,17 @@ async def test_function_approval_mode_rejection(streaming_chat_client_stub):
return "All data deleted"
async def stream_fn(
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
) -> AsyncIterator[ChatResponseUpdate]:
# Capture the messages received by the chat client
messages_received.clear()
messages_received.extend(messages)
yield ChatResponseUpdate(contents=[Content.from_text(text="Operation cancelled")])
agent = ChatAgent(
agent = Agent(
name="test_agent",
instructions="Test",
chat_client=streaming_chat_client_stub(stream_fn),
client=streaming_chat_client_stub(stream_fn),
tools=[delete_all_data],
)
wrapper = AgentFrameworkAgent(agent=agent)
@@ -5,7 +5,7 @@
import json
import pytest
from agent_framework import ChatAgent, ChatResponseUpdate, Content
from agent_framework import Agent, ChatResponseUpdate, Content
from fastapi import FastAPI, Header, HTTPException
from fastapi.params import Depends
from fastapi.testclient import TestClient
@@ -28,7 +28,7 @@ def build_chat_client(streaming_chat_client_stub, stream_from_updates_fixture):
async def test_add_endpoint_with_agent_protocol(build_chat_client):
"""Test adding endpoint with raw SupportsAgentRun."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/test-agent")
@@ -42,7 +42,7 @@ async def test_add_endpoint_with_agent_protocol(build_chat_client):
async def test_add_endpoint_with_wrapped_agent(build_chat_client):
"""Test adding endpoint with pre-wrapped AgentFrameworkAgent."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
wrapped_agent = AgentFrameworkAgent(agent=agent, name="wrapped")
add_agent_framework_fastapi_endpoint(app, wrapped_agent, path="/wrapped-agent")
@@ -57,7 +57,7 @@ async def test_add_endpoint_with_wrapped_agent(build_chat_client):
async def test_endpoint_with_state_schema(build_chat_client):
"""Test endpoint with state_schema parameter."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
state_schema = {"document": {"type": "string"}}
add_agent_framework_fastapi_endpoint(app, agent, path="/stateful", state_schema=state_schema)
@@ -73,7 +73,7 @@ async def test_endpoint_with_state_schema(build_chat_client):
async def test_endpoint_with_default_state_seed(build_chat_client):
"""Test endpoint seeds default state when client omits it."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
state_schema = {"proverbs": {"type": "array"}}
default_state = {"proverbs": ["Keep the original."]}
@@ -100,7 +100,7 @@ async def test_endpoint_with_default_state_seed(build_chat_client):
async def test_endpoint_with_predict_state_config(build_chat_client):
"""Test endpoint with predict_state_config parameter."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
predict_config = {"document": {"tool": "write_doc", "tool_argument": "content"}}
add_agent_framework_fastapi_endpoint(app, agent, path="/predictive", predict_state_config=predict_config)
@@ -114,7 +114,7 @@ async def test_endpoint_with_predict_state_config(build_chat_client):
async def test_endpoint_request_logging(build_chat_client):
"""Test that endpoint logs request details."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/logged")
@@ -134,7 +134,7 @@ async def test_endpoint_request_logging(build_chat_client):
async def test_endpoint_event_streaming(build_chat_client):
"""Test that endpoint streams events correctly."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client("Streamed response"))
agent = Agent(name="test", instructions="Test agent", client=build_chat_client("Streamed response"))
add_agent_framework_fastapi_endpoint(app, agent, path="/stream")
@@ -168,7 +168,7 @@ async def test_endpoint_event_streaming(build_chat_client):
async def test_endpoint_error_handling(build_chat_client):
"""Test endpoint error handling during request parsing."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/failing")
@@ -184,8 +184,8 @@ async def test_endpoint_error_handling(build_chat_client):
async def test_endpoint_multiple_paths(build_chat_client):
"""Test adding multiple endpoints with different paths."""
app = FastAPI()
agent1 = ChatAgent(name="agent1", instructions="First agent", chat_client=build_chat_client("Response 1"))
agent2 = ChatAgent(name="agent2", instructions="Second agent", chat_client=build_chat_client("Response 2"))
agent1 = Agent(name="agent1", instructions="First agent", client=build_chat_client("Response 1"))
agent2 = Agent(name="agent2", instructions="Second agent", client=build_chat_client("Response 2"))
add_agent_framework_fastapi_endpoint(app, agent1, path="/agent1")
add_agent_framework_fastapi_endpoint(app, agent2, path="/agent2")
@@ -202,7 +202,7 @@ async def test_endpoint_multiple_paths(build_chat_client):
async def test_endpoint_default_path(build_chat_client):
"""Test endpoint with default path."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent)
@@ -215,7 +215,7 @@ async def test_endpoint_default_path(build_chat_client):
async def test_endpoint_response_headers(build_chat_client):
"""Test that endpoint sets correct response headers."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/headers")
@@ -231,7 +231,7 @@ async def test_endpoint_response_headers(build_chat_client):
async def test_endpoint_empty_messages(build_chat_client):
"""Test endpoint with empty messages list."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/empty")
@@ -244,7 +244,7 @@ async def test_endpoint_empty_messages(build_chat_client):
async def test_endpoint_complex_input(build_chat_client):
"""Test endpoint with complex input data."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/complex")
@@ -269,7 +269,7 @@ async def test_endpoint_complex_input(build_chat_client):
async def test_endpoint_openapi_schema(build_chat_client):
"""Test that endpoint generates proper OpenAPI schema with request model."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/schema-test")
@@ -313,7 +313,7 @@ async def test_endpoint_openapi_schema(build_chat_client):
async def test_endpoint_default_tags(build_chat_client):
"""Test that endpoint uses default 'AG-UI' tag."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/default-tags")
@@ -331,7 +331,7 @@ async def test_endpoint_default_tags(build_chat_client):
async def test_endpoint_custom_tags(build_chat_client):
"""Test that endpoint accepts custom tags."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/custom-tags", tags=["Custom", "Agent"])
@@ -349,7 +349,7 @@ async def test_endpoint_custom_tags(build_chat_client):
async def test_endpoint_missing_required_field(build_chat_client):
"""Test that endpoint validates required fields with Pydantic."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
add_agent_framework_fastapi_endpoint(app, agent, path="/validation")
@@ -368,7 +368,7 @@ async def test_endpoint_internal_error_handling(build_chat_client):
from unittest.mock import patch
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
# Use default_state to trigger the code path that can raise an exception
add_agent_framework_fastapi_endpoint(app, agent, path="/error-test", default_state={"key": "value"})
@@ -387,7 +387,7 @@ async def test_endpoint_internal_error_handling(build_chat_client):
async def test_endpoint_with_dependencies_blocks_unauthorized(build_chat_client):
"""Test that endpoint blocks requests when authentication dependency fails."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
async def require_api_key(x_api_key: str | None = Header(None)):
if x_api_key != "secret-key":
@@ -406,7 +406,7 @@ async def test_endpoint_with_dependencies_blocks_unauthorized(build_chat_client)
async def test_endpoint_with_dependencies_allows_authorized(build_chat_client):
"""Test that endpoint allows requests when authentication dependency passes."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
async def require_api_key(x_api_key: str | None = Header(None)):
if x_api_key != "secret-key":
@@ -429,7 +429,7 @@ async def test_endpoint_with_dependencies_allows_authorized(build_chat_client):
async def test_endpoint_with_multiple_dependencies(build_chat_client):
"""Test that endpoint supports multiple dependencies."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
execution_order: list[str] = []
@@ -457,7 +457,7 @@ async def test_endpoint_with_multiple_dependencies(build_chat_client):
async def test_endpoint_without_dependencies_is_accessible(build_chat_client):
"""Test that endpoint without dependencies remains accessible (backward compatibility)."""
app = FastAPI()
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
# No dependencies parameter - should be accessible without auth
add_agent_framework_fastapi_endpoint(app, agent, path="/open")
@@ -2,7 +2,7 @@
"""Tests for orchestration helper functions."""
from agent_framework import ChatMessage, Content
from agent_framework import Content, Message
from agent_framework_ag_ui._orchestration._helpers import (
approval_steps,
@@ -29,8 +29,8 @@ class TestPendingToolCallIds:
def test_no_tool_calls(self):
"""Returns empty set when no tool calls in messages."""
messages = [
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
ChatMessage(role="assistant", contents=[Content.from_text("Hi there")]),
Message(role="user", contents=[Content.from_text("Hello")]),
Message(role="assistant", contents=[Content.from_text("Hi there")]),
]
result = pending_tool_call_ids(messages)
assert result == set()
@@ -38,7 +38,7 @@ class TestPendingToolCallIds:
def test_pending_tool_call(self):
"""Returns pending tool call ID when no result exists."""
messages = [
ChatMessage(
Message(
role="assistant",
contents=[Content.from_function_call(call_id="call_123", name="get_weather", arguments="{}")],
),
@@ -49,11 +49,11 @@ class TestPendingToolCallIds:
def test_resolved_tool_call(self):
"""Returns empty set when tool call has result."""
messages = [
ChatMessage(
Message(
role="assistant",
contents=[Content.from_function_call(call_id="call_123", name="get_weather", arguments="{}")],
),
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call_123", result="sunny")],
),
@@ -64,7 +64,7 @@ class TestPendingToolCallIds:
def test_multiple_tool_calls_some_resolved(self):
"""Returns only unresolved tool call IDs."""
messages = [
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(call_id="call_1", name="tool_a", arguments="{}"),
@@ -72,11 +72,11 @@ class TestPendingToolCallIds:
Content.from_function_call(call_id="call_3", name="tool_c", arguments="{}"),
],
),
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call_1", result="result_a")],
),
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call_3", result="result_c")],
),
@@ -90,7 +90,7 @@ class TestIsStateContextMessage:
def test_state_context_message(self):
"""Returns True for state context message."""
message = ChatMessage(
message = Message(
role="system",
contents=[Content.from_text("Current state of the application: {}")],
)
@@ -98,7 +98,7 @@ class TestIsStateContextMessage:
def test_non_system_message(self):
"""Returns False for non-system message."""
message = ChatMessage(
message = Message(
role="user",
contents=[Content.from_text("Current state of the application: {}")],
)
@@ -106,7 +106,7 @@ class TestIsStateContextMessage:
def test_system_message_without_state_prefix(self):
"""Returns False for system message without state prefix."""
message = ChatMessage(
message = Message(
role="system",
contents=[Content.from_text("You are a helpful assistant.")],
)
@@ -114,7 +114,7 @@ class TestIsStateContextMessage:
def test_empty_contents(self):
"""Returns False for message with empty contents."""
message = ChatMessage(role="system", contents=[])
message = Message(role="system", contents=[])
assert is_state_context_message(message) is False
@@ -342,7 +342,7 @@ class TestLatestApprovalResponse:
def test_no_approval_response(self):
"""Returns None when no approval response in last message."""
messages = [
ChatMessage(role="assistant", contents=[Content.from_text("Hello")]),
Message(role="assistant", contents=[Content.from_text("Hello")]),
]
result = latest_approval_response(messages)
assert result is None
@@ -357,7 +357,7 @@ class TestLatestApprovalResponse:
function_call=fc,
)
messages = [
ChatMessage(role="user", contents=[approval_content]),
Message(role="user", contents=[approval_content]),
]
result = latest_approval_response(messages)
assert result is approval_content
@@ -5,7 +5,7 @@
import json
import pytest
from agent_framework import ChatMessage, Content
from agent_framework import Content, Message
from agent_framework_ag_ui._message_adapters import (
agent_framework_messages_to_agui,
@@ -24,7 +24,7 @@ def sample_agui_message():
@pytest.fixture
def sample_agent_framework_message():
"""Create a sample Agent Framework message."""
return ChatMessage(role="user", contents=[Content.from_text(text="Hello")], message_id="msg-123")
return Message(role="user", contents=[Content.from_text(text="Hello")], message_id="msg-123")
def test_agui_to_agent_framework_basic(sample_agui_message):
@@ -100,7 +100,7 @@ def test_agui_tool_result_to_agent_framework():
def test_agui_tool_approval_updates_tool_call_arguments():
"""Tool approval updates matching tool call arguments for snapshots and agent context.
The LLM context (ChatMessage) should contain only enabled steps, so the LLM
The LLM context (Message) should contain only enabled steps, so the LLM
generates responses based on what was actually approved/executed.
The raw messages (for MESSAGES_SNAPSHOT) should contain all steps with status,
@@ -446,7 +446,7 @@ def test_agui_with_tool_calls_to_agent_framework():
def test_agent_framework_to_agui_with_tool_calls():
"""Test converting Agent Framework message with tool calls to AG-UI."""
msg = ChatMessage(
msg = Message(
role="assistant",
contents=[
Content.from_text(text="Calling tool"),
@@ -471,7 +471,7 @@ def test_agent_framework_to_agui_with_tool_calls():
def test_agent_framework_to_agui_multiple_text_contents():
"""Test concatenating multiple text contents."""
msg = ChatMessage(
msg = Message(
role="assistant",
contents=[Content.from_text(text="Part 1 "), Content.from_text(text="Part 2")],
)
@@ -484,7 +484,7 @@ def test_agent_framework_to_agui_multiple_text_contents():
def test_agent_framework_to_agui_no_message_id():
"""Test message without message_id - should auto-generate ID."""
msg = ChatMessage(role="user", contents=[Content.from_text(text="Hello")])
msg = Message(role="user", contents=[Content.from_text(text="Hello")])
messages = agent_framework_messages_to_agui([msg])
@@ -496,7 +496,7 @@ def test_agent_framework_to_agui_no_message_id():
def test_agent_framework_to_agui_system_role():
"""Test system role conversion."""
msg = ChatMessage(role="system", contents=[Content.from_text(text="System")])
msg = Message(role="system", contents=[Content.from_text(text="System")])
messages = agent_framework_messages_to_agui([msg])
@@ -541,7 +541,7 @@ def test_extract_text_from_custom_contents():
def test_agent_framework_to_agui_function_result_dict():
"""Test converting FunctionResultContent with dict result to AG-UI."""
msg = ChatMessage(
msg = Message(
role="tool",
contents=[Content.from_function_result(call_id="call-123", result={"key": "value", "count": 42})],
message_id="msg-789",
@@ -558,7 +558,7 @@ def test_agent_framework_to_agui_function_result_dict():
def test_agent_framework_to_agui_function_result_none():
"""Test converting FunctionResultContent with None result to AG-UI."""
msg = ChatMessage(
msg = Message(
role="tool",
contents=[Content.from_function_result(call_id="call-123", result=None)],
message_id="msg-789",
@@ -574,7 +574,7 @@ def test_agent_framework_to_agui_function_result_none():
def test_agent_framework_to_agui_function_result_string():
"""Test converting FunctionResultContent with string result to AG-UI."""
msg = ChatMessage(
msg = Message(
role="tool",
contents=[Content.from_function_result(call_id="call-123", result="plain text result")],
message_id="msg-789",
@@ -589,7 +589,7 @@ def test_agent_framework_to_agui_function_result_string():
def test_agent_framework_to_agui_function_result_empty_list():
"""Test converting FunctionResultContent with empty list result to AG-UI."""
msg = ChatMessage(
msg = Message(
role="tool",
contents=[Content.from_function_result(call_id="call-123", result=[])],
message_id="msg-789",
@@ -611,7 +611,7 @@ def test_agent_framework_to_agui_function_result_single_text_content():
class MockTextContent:
text: str
msg = ChatMessage(
msg = Message(
role="tool",
contents=[Content.from_function_result(call_id="call-123", result=[MockTextContent("Hello from MCP!")])],
message_id="msg-789",
@@ -633,7 +633,7 @@ def test_agent_framework_to_agui_function_result_multiple_text_contents():
class MockTextContent:
text: str
msg = ChatMessage(
msg = Message(
role="tool",
contents=[
Content.from_function_result(
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.
from agent_framework import ChatMessage, Content
from agent_framework import Content, Message
from agent_framework_ag_ui._message_adapters import _deduplicate_messages, _sanitize_tool_history
@@ -13,7 +13,7 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
tool for the approval UI flow that shouldn't be sent to the LLM.
"""
messages = [
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(
@@ -23,7 +23,7 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
)
],
),
ChatMessage(
Message(
role="user",
contents=[Content.from_text(text='{"accepted": true}')],
),
@@ -44,11 +44,11 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
def test_deduplicate_messages_prefers_non_empty_tool_results() -> None:
messages = [
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call1", result="")],
),
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call1", result="result data")],
),
@@ -71,13 +71,13 @@ def test_convert_approval_results_to_tool_messages() -> None:
# Simulate what happens after _resolve_approval_responses:
# A user message contains function_result content (the executed tool result)
messages = [
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(call_id="call_123", name="my_mcp_tool", arguments="{}"),
],
),
ChatMessage(
Message(
role="user",
contents=[
Content.from_function_result(call_id="call_123", result="tool execution result"),
@@ -109,13 +109,13 @@ def test_convert_approval_results_preserves_other_user_content() -> None:
from agent_framework_ag_ui._run import _convert_approval_results_to_tool_messages
messages = [
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(call_id="call_123", name="my_tool", arguments="{}"),
],
),
ChatMessage(
Message(
role="user",
contents=[
Content.from_text(text="User also said something"),
@@ -152,12 +152,12 @@ def test_sanitize_tool_history_filters_confirm_changes_keeps_other_tools() -> No
"""
messages = [
# User asks something
ChatMessage(
Message(
role="user",
contents=[Content.from_text(text="What time is it?")],
),
# Assistant calls MCP tool + confirm_changes
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(call_id="call_1", name="get_datetime", arguments="{}"),
@@ -165,12 +165,12 @@ def test_sanitize_tool_history_filters_confirm_changes_keeps_other_tools() -> No
],
),
# Tool result for the actual MCP tool
ChatMessage(
Message(
role="tool",
contents=[Content.from_function_result(call_id="call_1", result="2024-01-01 12:00:00")],
),
# User asks something else
ChatMessage(
Message(
role="user",
contents=[Content.from_text(text="What's the date?")],
),
@@ -204,12 +204,12 @@ def test_sanitize_tool_history_filters_confirm_changes_from_assistant_messages()
respond with "Here's your 5-step plan" instead of "Here's your 2-step plan".
"""
messages = [
ChatMessage(
Message(
role="user",
contents=[Content.from_text(text="Build a robot")],
),
# Assistant message with both generate_task_steps and confirm_changes
ChatMessage(
Message(
role="assistant",
contents=[
Content.from_function_call(
@@ -225,7 +225,7 @@ def test_sanitize_tool_history_filters_confirm_changes_from_assistant_messages()
],
),
# Approval response
ChatMessage(
Message(
role="user",
contents=[
Content.from_function_approval_response(
@@ -6,7 +6,7 @@ from ag_ui.core import (
TextMessageEndEvent,
TextMessageStartEvent,
)
from agent_framework import ChatMessage, Content
from agent_framework import Content, Message
from agent_framework_ag_ui._run import (
FlowState,
@@ -212,7 +212,7 @@ class TestInjectStateContext:
def test_no_state_message(self):
"""Returns original messages when no state context needed."""
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
result = _inject_state_context(messages, {}, {})
assert result == messages
@@ -224,8 +224,8 @@ class TestInjectStateContext:
def test_last_message_not_user(self):
"""Returns original messages when last message is not from user."""
messages = [
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
ChatMessage(role="assistant", contents=[Content.from_text("Hi")]),
Message(role="user", contents=[Content.from_text("Hello")]),
Message(role="assistant", contents=[Content.from_text("Hi")]),
]
state = {"key": "value"}
schema = {"properties": {"key": {"type": "string"}}}
@@ -237,8 +237,8 @@ class TestInjectStateContext:
"""Injects state context before last user message."""
messages = [
ChatMessage(role="system", contents=[Content.from_text("You are helpful")]),
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
Message(role="system", contents=[Content.from_text("You are helpful")]),
Message(role="user", contents=[Content.from_text("Hello")]),
]
state = {"document": "content"}
schema = {"properties": {"document": {"type": "string"}}}
@@ -405,7 +405,7 @@ def test_extract_approved_state_updates_no_handler():
"""Test _extract_approved_state_updates returns empty with no handler."""
from agent_framework_ag_ui._run import _extract_approved_state_updates
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
result = _extract_approved_state_updates(messages, None)
assert result == {}
@@ -416,7 +416,7 @@ def test_extract_approved_state_updates_no_approval():
from agent_framework_ag_ui._run import _extract_approved_state_updates
handler = PredictiveStateHandler(predict_state_config={"doc": {"tool": "write", "tool_argument": "content"}})
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
result = _extract_approved_state_updates(messages, handler)
assert result == {}

Some files were not shown because too many files have changed in this diff Show More