mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbb2af3388 | ||
|
|
793403f3db | ||
|
|
9fdd7429a8 | ||
|
|
abc9b60ec9 | ||
|
|
6bc0dc5911 | ||
|
|
cf91819625 | ||
|
|
578416a379 | ||
|
|
8eac98f8c7 | ||
|
|
bca42febe2 | ||
|
|
6173f05936 | ||
|
|
bd632f2a38 |
@@ -212,6 +212,7 @@
|
||||
</Folder>
|
||||
<Folder Name="/Samples/02-agents/ModelContextProtocol/">
|
||||
<File Path="samples/02-agents/ModelContextProtocol/README.md" />
|
||||
<Project Path="samples/02-agents/ModelContextProtocol/Agent_MCP_LongRunningTask_Client/Agent_MCP_LongRunningTask_Client.csproj" />
|
||||
<Project Path="samples/02-agents/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj" />
|
||||
<Project Path="samples/02-agents/ModelContextProtocol/Agent_MCP_Server_Auth/Agent_MCP_Server_Auth.csproj" />
|
||||
<Project Path="samples/02-agents/ModelContextProtocol/FoundryAgent_Hosted_MCP/FoundryAgent_Hosted_MCP.csproj" />
|
||||
@@ -240,7 +241,6 @@
|
||||
<Project Path="samples/03-workflows/Declarative/ExecuteCode/ExecuteCode.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/ExecuteWorkflow/ExecuteWorkflow.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/FunctionTools/FunctionTools.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/GenerateCode/GenerateCode.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/HostedWorkflow/HostedWorkflow.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/InputArguments/InputArguments.csproj" />
|
||||
<Project Path="samples/03-workflows/Declarative/InvokeFunctionTool/InvokeFunctionTool.csproj" />
|
||||
@@ -281,6 +281,7 @@
|
||||
</Folder>
|
||||
<Folder Name="/Samples/03-workflows/Orchestration/">
|
||||
<Project Path="samples/03-workflows/Orchestration/Handoff/Handoff.csproj" />
|
||||
<Project Path="samples/03-workflows/Orchestration/Magentic/Magentic.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/03-workflows/Observability/">
|
||||
<Project Path="samples/03-workflows/Observability/ApplicationInsights/ApplicationInsights.csproj" />
|
||||
@@ -601,6 +602,7 @@
|
||||
<Project Path="src/Microsoft.Agents.AI.Hosting.OpenAI/Microsoft.Agents.AI.Hosting.OpenAI.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Hosting/Microsoft.Agents.AI.Hosting.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Hyperlight/Microsoft.Agents.AI.Hyperlight.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Mcp/Microsoft.Agents.AI.Mcp.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Mem0/Microsoft.Agents.AI.Mem0.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Purview/Microsoft.Agents.AI.Purview.csproj" />
|
||||
@@ -654,6 +656,7 @@
|
||||
<Project Path="tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.Hosting.UnitTests/Microsoft.Agents.AI.Hosting.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.Hyperlight.UnitTests/Microsoft.Agents.AI.Hyperlight.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.Mcp.UnitTests/Microsoft.Agents.AI.Mcp.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.Mem0.UnitTests/Microsoft.Agents.AI.Mem0.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.OpenAI.UnitTests/Microsoft.Agents.AI.OpenAI.UnitTests.csproj" />
|
||||
<Project Path="tests/Microsoft.Agents.AI.Purview.UnitTests/Microsoft.Agents.AI.Purview.UnitTests.csproj" />
|
||||
|
||||
@@ -1151,6 +1151,25 @@ internal static class AgentsSamples
|
||||
SkipReason = "Runs as an MCP stdio server that does not exit on its own.",
|
||||
},
|
||||
|
||||
new SampleDefinition
|
||||
{
|
||||
Name = "Agent_MCP_LongRunningTask_Client",
|
||||
ProjectPath = "samples/02-agents/ModelContextProtocol/Agent_MCP_LongRunningTask_Client",
|
||||
RequiredEnvironmentVariables = ["AZURE_OPENAI_ENDPOINT"],
|
||||
OptionalEnvironmentVariables = ["AZURE_OPENAI_DEPLOYMENT_NAME"],
|
||||
MustContain =
|
||||
[
|
||||
"=== Transparent long-running MCP task (RunAsync) ===",
|
||||
"=== Transparent long-running MCP task (RunStreamingAsync) ===",
|
||||
],
|
||||
ExpectedOutputDescription =
|
||||
[
|
||||
"The output should show an agent analyzing a dataset named 'sales-2025-q1' and producing a summary mentioning rows, revenue, anomalies, or outliers.",
|
||||
"The output should contain both a non-streaming response (after RunAsync) and a streaming response (after RunStreamingAsync) for the same analysis question.",
|
||||
"The output should not contain error messages or stack traces.",
|
||||
],
|
||||
},
|
||||
|
||||
new SampleDefinition
|
||||
{
|
||||
Name = "AGUI_Step01_GettingStarted_Client",
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);MAAI001;MEAI001;MCPEXP001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="ModelContextProtocol" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Mcp\Microsoft.Agents.AI.Mcp.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates the Microsoft Agent Framework's MCP long-running task support.
|
||||
//
|
||||
// A small MCP server (hosted in this same executable when launched with "--server") exposes
|
||||
// a single task-supporting tool "AnalyzeDataset" that simulates ~15 seconds of work. The
|
||||
// client (default mode) connects to it over stdio via Microsoft.Agents.AI.Mcp's
|
||||
// McpClientTaskExtensions.ListAgentToolsWithTaskSupportAsync, hands the wrapped tools to a
|
||||
// ChatClientAgent, and exercises both invocation styles:
|
||||
// * RunAsync — blocks until the agent's final response is ready.
|
||||
// * RunStreamingAsync — yields response updates as the model produces them; the model
|
||||
// still waits for the tool's terminal result before it can begin
|
||||
// producing the final answer, so the perceived "pause" reflects
|
||||
// tool execution time, not stream-channel latency.
|
||||
//
|
||||
// In both cases the wrapper transparently:
|
||||
// 1. Calls tools/call with task augmentation (CallToolAsTaskAsync)
|
||||
// 2. Polls tasks/get until terminal (PollTaskUntilCompleteAsync)
|
||||
// 3. Fetches tasks/result and returns the final result to the function-calling loop
|
||||
//
|
||||
// No application-level loop or continuation tokens are required in either mode.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Mcp;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ModelContextProtocol;
|
||||
using ModelContextProtocol.Client;
|
||||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
using OpenAI.Chat;
|
||||
|
||||
if (args.Length > 0 && args[0] == "--server")
|
||||
{
|
||||
await RunMcpServerAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-5.4-mini";
|
||||
|
||||
// Launch this same assembly as a stdio MCP server in a child process.
|
||||
var thisAssemblyPath = typeof(Program).Assembly.Location;
|
||||
await using var mcpClient = await McpClient.CreateAsync(new StdioClientTransport(new()
|
||||
{
|
||||
Name = "DatasetAnalyzer",
|
||||
Command = "dotnet",
|
||||
Arguments = [thisAssemblyPath, "--server"],
|
||||
}));
|
||||
|
||||
// Wrap each MCP tool with task-aware behavior. The wrapper inspects the server's
|
||||
// execution.taskSupport on each tool and, when it is Required, drives the task lifecycle
|
||||
// transparently within the agent's tool loop. Tools that don't require task semantics are
|
||||
// returned as-is and invoked inline.
|
||||
var taskOptions = new McpTaskOptions
|
||||
{
|
||||
DefaultTimeToLive = TimeSpan.FromMinutes(5),
|
||||
};
|
||||
var mcpTools = await mcpClient.ListAgentToolsWithTaskSupportAsync(taskOptions);
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new DefaultAzureCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsAIAgent(
|
||||
instructions: "You answer data-analysis questions by invoking the available tools. Always invoke a tool when one matches the request.",
|
||||
tools: [.. mcpTools.Cast<AITool>()]);
|
||||
|
||||
const string Prompt = "Analyze the dataset named 'sales-2025-q1' and summarize the findings.";
|
||||
|
||||
Console.WriteLine("=== Transparent long-running MCP task (RunAsync) ===");
|
||||
Console.WriteLine("Asking the agent to analyze a dataset; the tool takes ~15s to complete.");
|
||||
Console.WriteLine("RunAsync blocks while the wrapper polls the task to completion.");
|
||||
Console.WriteLine();
|
||||
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
var response = await agent.RunAsync(Prompt);
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine($"Agent response (after {stopwatch.Elapsed.TotalSeconds:F1}s):");
|
||||
Console.WriteLine(response.Text);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("=== Transparent long-running MCP task (RunStreamingAsync) ===");
|
||||
Console.WriteLine("Same request via the streaming API. Updates only begin to arrive after the");
|
||||
Console.WriteLine("tool's task reaches the Completed state, since the model needs the tool result");
|
||||
Console.WriteLine("before it can produce its final answer.");
|
||||
Console.WriteLine();
|
||||
|
||||
stopwatch.Restart();
|
||||
await foreach (var update in agent.RunStreamingAsync(Prompt))
|
||||
{
|
||||
Console.Write(update.Text);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"(Streaming completed after {stopwatch.Elapsed.TotalSeconds:F1}s.)");
|
||||
|
||||
// --- Server mode (launched as a child process via --server) ---------------------------------
|
||||
static async Task RunMcpServerAsync()
|
||||
{
|
||||
var builder = Host.CreateApplicationBuilder();
|
||||
|
||||
// Critical for stdio transport: any provider that writes to stdout will corrupt the
|
||||
// JSON-RPC channel. Clear all providers; the MCP SDK routes its own diagnostics
|
||||
// appropriately.
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Logging.AddConsole(o => o.LogToStandardErrorThreshold = LogLevel.Trace);
|
||||
|
||||
builder.Services.AddMcpServer(o =>
|
||||
{
|
||||
o.TaskStore = new InMemoryMcpTaskStore();
|
||||
o.ServerInfo = new Implementation { Name = "DatasetAnalyzer", Version = "1.0.0" };
|
||||
})
|
||||
.WithStdioServerTransport()
|
||||
.WithTools<DatasetAnalysisTools>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
}
|
||||
|
||||
#pragma warning disable CA1812 // Discovered by MCP SDK via [McpServerToolType] attribute
|
||||
[McpServerToolType]
|
||||
internal sealed class DatasetAnalysisTools
|
||||
#pragma warning restore CA1812
|
||||
{
|
||||
[McpServerTool(Name = "AnalyzeDataset", TaskSupport = ToolTaskSupport.Required)]
|
||||
[Description("Analyze a tabular dataset and return summary statistics. This tool simulates a long-running analytic job (~15 seconds).")]
|
||||
public static async Task<string> AnalyzeDatasetAsync(
|
||||
[Description("The dataset identifier, e.g. 'sales-2025-q1'.")] string datasetName,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(15), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return $"Findings for '{datasetName}': 12,403 rows; avg revenue $48,712; 3 anomalies detected in week 7; outliers concentrated in EMEA region.";
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
# Agent with MCP long-running task (transparent polling)
|
||||
|
||||
This sample demonstrates Microsoft Agent Framework's MCP long-running task support: an agent invokes an MCP tool whose execution takes too long for a single request/response cycle, and the framework polls it to completion behind the function-calling loop. From the agent's perspective the tool simply returns its result.
|
||||
|
||||
## What this sample shows
|
||||
|
||||
- Using `McpClient.ListAgentToolsWithTaskSupportAsync(...)` (in `Microsoft.Agents.AI.Mcp`) to wrap MCP tools with task-aware behavior.
|
||||
- Configuring `McpTaskOptions.DefaultTimeToLive` to bound the server-side task.
|
||||
- Hosting a small MCP server (in this same executable, launched with `--server`) that advertises `execution.taskSupport=required` on a tool that sleeps for ~15 seconds.
|
||||
- No application-level polling, continuation tokens, or `AllowBackgroundResponses` flag are required.
|
||||
|
||||
The decorator drives the lifecycle internally:
|
||||
|
||||
1. `tools/call` augmented with task metadata (`CallToolAsTaskAsync`)
|
||||
2. `tasks/get` polled until terminal (`PollTaskUntilCompleteAsync`)
|
||||
3. `tasks/result` retrieved (`GetTaskResultAsync`) and returned to the function-calling loop
|
||||
|
||||
The sample exercises both invocation styles against the same wrapper:
|
||||
|
||||
- `agent.RunAsync(...)` blocks until the tool completes (~15 seconds in this sample) and returns the final response.
|
||||
- `agent.RunStreamingAsync(...)` returns immediately and yields `AgentResponseUpdate` chunks as the model emits them; in this scenario the model only begins streaming its answer once the wrapped tool's task reaches the `Completed` state, so the perceived "pause" before tokens arrive reflects tool execution time, not stream-channel latency.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Azure OpenAI service endpoint and a chat-completions deployment
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-5.4-mini" # optional; defaults to gpt-5.4-mini
|
||||
```
|
||||
|
||||
# Running
|
||||
|
||||
```powershell
|
||||
cd Agent_MCP_LongRunningTask_Client
|
||||
dotnet run
|
||||
```
|
||||
|
||||
You should see output similar to:
|
||||
|
||||
```
|
||||
=== Transparent long-running MCP task (RunAsync) ===
|
||||
Asking the agent to analyze a dataset; the tool takes ~15s to complete.
|
||||
RunAsync blocks while the wrapper polls the task to completion.
|
||||
|
||||
Agent response (after 15.4s):
|
||||
The 'sales-2025-q1' dataset contains 12,403 rows ...
|
||||
|
||||
=== Transparent long-running MCP task (RunStreamingAsync) ===
|
||||
Same request via the streaming API. Updates only begin to arrive after the
|
||||
tool's task reaches the Completed state, since the model needs the tool result
|
||||
before it can produce its final answer.
|
||||
|
||||
The 'sales-2025-q1' dataset contains 12,403 rows ...
|
||||
(Streaming completed after 15.7s.)
|
||||
```
|
||||
@@ -22,6 +22,7 @@ Before you begin, ensure you have the following prerequisites:
|
||||
|[Agent with MCP server tools](./Agent_MCP_Server/)|This sample demonstrates how to use MCP server tools with a simple agent|
|
||||
|[Agent with MCP server tools and authorization](./Agent_MCP_Server_Auth/)|This sample demonstrates how to use MCP Server tools from a protected MCP server with a simple agent|
|
||||
|[Responses Agent with Hosted MCP tool](./ResponseAgent_Hosted_MCP/)|This sample demonstrates how to use the Hosted MCP tool with the Responses Service, where the service invokes any MCP tools directly|
|
||||
|[Agent with long-running MCP task (transparent polling)](./Agent_MCP_LongRunningTask_Client/)|This sample demonstrates how an agent transparently drives a long-running MCP task (SEP-2663) to completion. The wrapper polls the task internally on both `RunAsync` and `RunStreamingAsync` invocations.|
|
||||
|
||||
## Running the samples from the console
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>
|
||||
<NoWarn>$(NoWarn);CA1812</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows.Declarative\Microsoft.Agents.AI.Workflows.Declarative.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,105 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative;
|
||||
|
||||
namespace Demo.DeclarativeEject;
|
||||
|
||||
/// <summary>
|
||||
/// HOW TO: Convert a workflow from a declartive (yaml based) definition to code.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <b>Usage</b>
|
||||
/// Provide the path to the workflow definition file as the first argument.
|
||||
/// All other arguments are intepreted as a queue of inputs.
|
||||
/// When no input is queued, interactive input is requested from the console.
|
||||
/// </remarks>
|
||||
internal sealed class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Program program = new(args);
|
||||
program.Execute();
|
||||
}
|
||||
|
||||
private void Execute()
|
||||
{
|
||||
// Read and parse the declarative workflow.
|
||||
Notify($"WORKFLOW: Parsing {Path.GetFullPath(this.WorkflowFile)}");
|
||||
|
||||
Stopwatch timer = Stopwatch.StartNew();
|
||||
|
||||
// Use DeclarativeWorkflowBuilder to generate code based on a YAML file.
|
||||
string code =
|
||||
DeclarativeWorkflowBuilder.Eject(
|
||||
this.WorkflowFile,
|
||||
DeclarativeWorkflowLanguage.CSharp,
|
||||
workflowNamespace: "Demo.DeclarativeCode",
|
||||
workflowPrefix: "Sample");
|
||||
|
||||
Notify($"\nWORKFLOW: Defined {timer.Elapsed}\n");
|
||||
|
||||
Console.WriteLine(code);
|
||||
}
|
||||
|
||||
private const string DefaultWorkflow = "Marketing.yaml";
|
||||
|
||||
private string WorkflowFile { get; }
|
||||
|
||||
private Program(string[] args)
|
||||
{
|
||||
this.WorkflowFile = ParseWorkflowFile(args);
|
||||
}
|
||||
|
||||
private static string ParseWorkflowFile(string[] args)
|
||||
{
|
||||
string workflowFile = args.FirstOrDefault() ?? DefaultWorkflow;
|
||||
|
||||
if (!File.Exists(workflowFile) && !Path.IsPathFullyQualified(workflowFile))
|
||||
{
|
||||
string? repoFolder = GetRepoFolder();
|
||||
if (repoFolder is not null)
|
||||
{
|
||||
workflowFile = Path.Combine(repoFolder, "declarative-agents", "workflow-samples", workflowFile);
|
||||
workflowFile = Path.ChangeExtension(workflowFile, ".yaml");
|
||||
}
|
||||
}
|
||||
|
||||
if (!File.Exists(workflowFile))
|
||||
{
|
||||
throw new InvalidOperationException($"Unable to locate workflow: {Path.GetFullPath(workflowFile)}.");
|
||||
}
|
||||
|
||||
return workflowFile;
|
||||
|
||||
static string? GetRepoFolder()
|
||||
{
|
||||
DirectoryInfo? current = new(Directory.GetCurrentDirectory());
|
||||
|
||||
while (current is not null)
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(current.FullName, ".git")))
|
||||
{
|
||||
return current.FullName;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Notify(string message)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||
try
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Marketing": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"Marketing.yaml\""
|
||||
},
|
||||
"MathChat": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"MathChat.yaml\""
|
||||
},
|
||||
"Question": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"Question.yaml\""
|
||||
},
|
||||
"Research": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"DeepResearch.yaml\""
|
||||
},
|
||||
"ResponseObject": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"ResponseObject.yaml\""
|
||||
},
|
||||
"UserInput": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"UserInput.yaml\""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);MAAIW001;OPENAI001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Foundry\Microsoft.Agents.AI.Foundry.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,193 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample ports the Python Magentic orchestration sample to .NET.
|
||||
// A Magentic workflow coordinates a researcher and a coder, streams orchestration
|
||||
// events as the plan evolves, and prints the final conversation transcript.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Agents.AI.Workflows.Specialized.Magentic;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace WorkflowMagenticOrchestrationSample;
|
||||
|
||||
/// <summary>
|
||||
/// Demonstrates Magentic orchestration with a researcher, a coder, and an LLM manager.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Pre-requisites:
|
||||
/// - An Azure AI Foundry project endpoint and model deployment must be configured.
|
||||
/// - Run <c>az login</c> before executing the sample.
|
||||
/// </remarks>
|
||||
public static class Program
|
||||
{
|
||||
private const string TaskPrompt =
|
||||
"I am preparing a report on the energy efficiency of different machine learning model architectures. " +
|
||||
"Compare the estimated training and inference energy consumption of ResNet-50, BERT-base, and GPT-2 " +
|
||||
"on standard datasets (e.g., ImageNet for ResNet, GLUE for BERT, WebText for GPT-2). " +
|
||||
"Then, estimate the CO2 emissions associated with each, assuming training on an Azure Standard_NC6s_v3 " +
|
||||
"VM for 24 hours. Provide tables for clarity, and recommend the most energy-efficient model " +
|
||||
"per task type (image classification, text classification, and text generation).";
|
||||
|
||||
private static async Task Main()
|
||||
{
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
|
||||
?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-5.4-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient projectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AIAgent researcherAgent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
name: "ResearcherAgent",
|
||||
description: "Specialist in research and information gathering.",
|
||||
instructions: "You are a researcher. Find relevant information without doing additional computation or quantitative analysis.");
|
||||
|
||||
AIAgent coderAgent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
name: "CoderAgent",
|
||||
description: "A helpful assistant that writes and executes code to analyze data.",
|
||||
instructions: "You solve quantitative questions by writing and running code. Show the analysis and the computation process clearly.",
|
||||
tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
AIAgent managerAgent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
name: "MagenticManager",
|
||||
description: "Orchestrator that coordinates the research and coding workflow.",
|
||||
instructions: "You coordinate the team to complete complex tasks efficiently.");
|
||||
|
||||
Workflow workflow = new MagenticWorkflowBuilder(managerAgent)
|
||||
.AddParticipants([researcherAgent, coderAgent])
|
||||
.WithName("Magentic Orchestration Workflow")
|
||||
.WithDescription("Coordinates a researcher and coder to solve a complex analytical task.")
|
||||
.RequirePlanSignoff(false)
|
||||
.WithMaxRounds(10)
|
||||
.WithMaxStalls(3)
|
||||
.WithMaxResets(2)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Building Magentic workflow...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Task: {TaskPrompt}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Starting workflow execution...");
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(
|
||||
workflow,
|
||||
new List<ChatMessage> { new(ChatRole.User, TaskPrompt) });
|
||||
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastResponseId = null;
|
||||
WorkflowOutputEvent? finalOutput = null;
|
||||
|
||||
await foreach (WorkflowEvent workflowEvent in run.WatchStreamAsync())
|
||||
{
|
||||
switch (workflowEvent)
|
||||
{
|
||||
case AgentResponseUpdateEvent updateEvent:
|
||||
WriteStreamingUpdate(updateEvent, ref lastResponseId);
|
||||
break;
|
||||
|
||||
case MagenticPlanCreatedEvent planCreated:
|
||||
WriteMagenticMessage("Initial Plan", planCreated.FullTaskLedger.Text);
|
||||
PauseIfInteractive();
|
||||
break;
|
||||
|
||||
case MagenticReplannedEvent replanned:
|
||||
WriteMagenticMessage("Replanned", replanned.FullTaskLedger.Text);
|
||||
PauseIfInteractive();
|
||||
break;
|
||||
|
||||
case MagenticProgressLedgerUpdatedEvent progressUpdated:
|
||||
WriteMagenticMessage("Progress Ledger", FormatProgressLedger(progressUpdated.ProgressLedger));
|
||||
PauseIfInteractive();
|
||||
break;
|
||||
|
||||
case WorkflowOutputEvent outputEvent when outputEvent.Is<List<ChatMessage>>():
|
||||
finalOutput = outputEvent;
|
||||
break;
|
||||
|
||||
case WorkflowErrorEvent workflowError:
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Error.WriteLine(workflowError.Exception?.ToString() ?? "Unknown workflow error occurred.");
|
||||
Console.ResetColor();
|
||||
break;
|
||||
|
||||
case ExecutorFailedEvent executorFailed:
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Error.WriteLine($"Executor '{executorFailed.ExecutorId}' failed with {(executorFailed.Data is null ? "unknown error" : $"exception {executorFailed.Data}")}.");
|
||||
Console.ResetColor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalOutput?.As<List<ChatMessage>>() is { } transcript)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(new string('=', 80));
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Final Conversation Transcript:");
|
||||
Console.WriteLine();
|
||||
|
||||
foreach (ChatMessage message in transcript)
|
||||
{
|
||||
Console.WriteLine($"{message.AuthorName ?? message.Role.ToString()}: {message.Text}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteStreamingUpdate(AgentResponseUpdateEvent updateEvent, ref string? lastResponseId)
|
||||
{
|
||||
string responseId = updateEvent.Update.ResponseId ?? updateEvent.Update.MessageId ?? updateEvent.ExecutorId;
|
||||
if (!string.Equals(responseId, lastResponseId, StringComparison.Ordinal))
|
||||
{
|
||||
if (lastResponseId is not null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.Write($"- {updateEvent.ExecutorId}: ");
|
||||
lastResponseId = responseId;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(updateEvent.Update.Text))
|
||||
{
|
||||
Console.Write(updateEvent.Update.Text);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteMagenticMessage(string title, string? content)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"[Magentic {title}]");
|
||||
Console.WriteLine(content);
|
||||
}
|
||||
|
||||
private static string FormatProgressLedger(MagenticProgressLedger ledger) =>
|
||||
string.Join(Environment.NewLine,
|
||||
$"Request satisfied: {ledger.IsRequestSatisfied}",
|
||||
$"In loop: {ledger.IsInLoop}",
|
||||
$"Making progress: {ledger.IsProgressBeingMade}",
|
||||
$"Next speaker: {ledger.NextSpeaker}",
|
||||
$"Instruction: {ledger.InstructionOrQuestion}");
|
||||
|
||||
private static void PauseIfInteractive()
|
||||
{
|
||||
if (Console.IsInputRedirected || Console.IsOutputRedirected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Write("Press Enter to continue...");
|
||||
Console.ReadLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Magentic Orchestration Sample
|
||||
|
||||
This sample showcases the Magentic Orchestration Pattern in .NET, setting up a team with three roles:
|
||||
|
||||
- **ResearcherAgent** gathers factual background information.
|
||||
- **CoderAgent** uses `HostedCodeInterpreterTool` for quantitative analysis.
|
||||
- **MagenticManager** plans the work, tracks progress, and decides who should act next.
|
||||
|
||||
## What This Sample Demonstrates
|
||||
|
||||
- Building a Magentic workflow with `MagenticWorkflowBuilder`
|
||||
- Combining standard responses-based agents with a code interpreter-enabled participant
|
||||
- Streaming orchestration events such as the initial plan, replans, and progress-ledger updates
|
||||
- Printing the final multi-agent conversation transcript
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- `AZURE_AI_PROJECT_ENDPOINT` set to your Azure AI Foundry project endpoint
|
||||
- `AZURE_AI_MODEL_DEPLOYMENT_NAME` set to your model deployment name (defaults to `gpt-5.4-mini`)
|
||||
- `az login` completed before running the sample
|
||||
|
||||
## Running the Sample
|
||||
|
||||
```bash
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
The sample prints:
|
||||
|
||||
1. The original task prompt
|
||||
2. Streamed updates from the participating agents
|
||||
3. Magentic plan and progress-ledger events as the workflow coordinates the team
|
||||
4. The final conversation transcript returned by the workflow
|
||||
|
||||
## Related Samples
|
||||
|
||||
- [Handoff Orchestration](../Handoff) - another multi-agent orchestration pattern in .NET workflows
|
||||
- [Python Magentic workflow sample](../../../../../python/samples/03-workflows/orchestrations/magentic.py) - the source scenario that this sample ports
|
||||
@@ -62,3 +62,4 @@ Once completed, please proceed to the other samples listed below.
|
||||
| Sample | Concepts |
|
||||
|--------|----------|
|
||||
| [Handoff Orchestration](./Orchestration/Handoff) | Introduces the Handoff Orchestration pattern |
|
||||
| [Magentic Orchestration](./Orchestration/Magentic) | Coordinates multiple agents with a Magentic manager, streamed plan events, and a final transcript |
|
||||
|
||||
@@ -474,6 +474,7 @@ public sealed class A2AAgent : AIAgent
|
||||
ResponseId = statusUpdateEvent.TaskId,
|
||||
RawRepresentation = statusUpdateEvent,
|
||||
Role = ChatRole.Assistant,
|
||||
MessageId = statusUpdateEvent.Status.Message?.MessageId,
|
||||
FinishReason = MapTaskStateToFinishReason(statusUpdateEvent.Status.State),
|
||||
AdditionalProperties = statusUpdateEvent.Metadata?.ToAdditionalProperties() ?? [],
|
||||
Contents = statusUpdateEvent.Status.GetUserInputRequests(),
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
using ModelContextProtocol.Client;
|
||||
using ModelContextProtocol.Protocol;
|
||||
|
||||
namespace Microsoft.Agents.AI.Mcp;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods on <see cref="McpClient"/> that expose MCP server tools to a Microsoft
|
||||
/// Agent Framework agent with optional long-running task (SEP-2663) handling.
|
||||
/// </summary>
|
||||
public static class McpClientTaskExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Lists tools advertised by the connected MCP server and returns each as an
|
||||
/// <see cref="AIFunction"/>. Tools that declare <see cref="ToolTaskSupport.Required"/>
|
||||
/// are wrapped with task-aware behavior so an agent can transparently drive long-running
|
||||
/// invocations. All other tools — including those that declare
|
||||
/// <see cref="ToolTaskSupport.Optional"/> — are returned as-is, preserving inline
|
||||
/// (synchronous) invocation semantics by default.
|
||||
/// </summary>
|
||||
/// <param name="client">The connected MCP client.</param>
|
||||
/// <param name="options">
|
||||
/// Options that control the task lifecycle for task-capable tools.
|
||||
/// When <see langword="null"/>, defaults described on <see cref="McpTaskOptions"/> apply.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">Token used to cancel listing the server's tools.</param>
|
||||
/// <returns>The tools, ready to pass to <c>AsAIAgent(tools: …)</c>.</returns>
|
||||
public static async Task<IReadOnlyList<AIFunction>> ListAgentToolsWithTaskSupportAsync(
|
||||
this McpClient client,
|
||||
McpTaskOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
_ = Throw.IfNull(client);
|
||||
|
||||
McpTaskOptions effectiveOptions = options ?? new McpTaskOptions();
|
||||
|
||||
IList<McpClientTool> tools = await client.ListToolsAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
AIFunction[] result = new AIFunction[tools.Count];
|
||||
for (int i = 0; i < tools.Count; i++)
|
||||
{
|
||||
ToolTaskSupport? taskSupport = tools[i].ProtocolTool.Execution?.TaskSupport;
|
||||
if (taskSupport is ToolTaskSupport.Required)
|
||||
{
|
||||
result[i] = new TaskAwareMcpClientAIFunction(client, tools[i], effectiveOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
result[i] = tools[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Agents.AI.Mcp;
|
||||
|
||||
/// <summary>
|
||||
/// Configures how an MCP client wrapper drives the
|
||||
/// <see href="https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks">MCP tasks</see>
|
||||
/// lifecycle when an underlying server tool returns a <c>CreateTaskResult</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// All members of this type are subject to change. The MCP task surface is experimental
|
||||
/// and tracks the in-flight specification.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public sealed class McpTaskOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live the wrapper attaches to a newly created server-side task.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When <see langword="null"/> the wrapper omits the <c>ttl</c> hint and lets the server
|
||||
/// pick its own value. The server's chosen TTL is always authoritative.
|
||||
/// </remarks>
|
||||
public TimeSpan? DefaultTimeToLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the wrapper should send
|
||||
/// <c>tasks/cancel</c> when the local <see cref="System.Threading.CancellationToken"/>
|
||||
/// fires during a tool invocation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Defaults to <see langword="true"/>: a local cancellation means "the caller is giving up
|
||||
/// on this tool invocation" and the server-side task has no further consumer.
|
||||
/// </remarks>
|
||||
public bool CancelRemoteTaskOnLocalCancellation { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(TargetFrameworksCore)</TargetFrameworks>
|
||||
<RootNamespace>Microsoft.Agents.AI.Mcp</RootNamespace>
|
||||
<VersionSuffix>alpha</VersionSuffix>
|
||||
<NoWarn>$(NoWarn);MEAI001;MCPEXP001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(RepoRoot)/dotnet/nuget/nuget-package.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
<InjectTrimAttributesOnLegacy>true</InjectTrimAttributesOnLegacy>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Title>Microsoft Agent Framework MCP</Title>
|
||||
<Description>Provides Microsoft Agent Framework support for Model Context Protocol (MCP), including long-running task (SEP-2663) integration for MCP clients.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Disable package validation baseline until the first release -->
|
||||
<PropertyGroup>
|
||||
<PackageValidationBaselineVersion />
|
||||
<EnablePackageValidation>false</EnablePackageValidation>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.AI" />
|
||||
<PackageReference Include="ModelContextProtocol" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Microsoft.Agents.AI.Mcp.UnitTests" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
using ModelContextProtocol;
|
||||
using ModelContextProtocol.Client;
|
||||
using ModelContextProtocol.Protocol;
|
||||
|
||||
namespace Microsoft.Agents.AI.Mcp;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="AIFunction"/> wrapper around an <see cref="McpClientTool"/> that drives the
|
||||
/// <see href="https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks">MCP long-running task</see>
|
||||
/// lifecycle (SEP-2663) on behalf of the agent's tool loop.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The wrapper invokes the tool with task augmentation via
|
||||
/// <see cref="McpClient.CallToolAsTaskAsync"/>, polls to completion via
|
||||
/// <see cref="McpClient.PollTaskUntilCompleteAsync"/>, and fetches the result via
|
||||
/// <see cref="McpClient.GetTaskResultAsync"/>. The result is returned to the caller as a
|
||||
/// <see cref="JsonElement"/> containing the serialized <see cref="CallToolResult"/> — the
|
||||
/// same wire shape produced by <see cref="McpClientTool"/>.<see cref="AIFunction.InvokeAsync(AIFunctionArguments, CancellationToken)"/>
|
||||
/// so that downstream <see cref="FunctionResultContent"/> serialization is byte-identical to
|
||||
/// a non-task-augmented MCP tool call. The agent's function-calling loop is unaware that a
|
||||
/// task was used.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This wrapper is intended to be applied only to tools whose
|
||||
/// <see cref="ToolExecution.TaskSupport"/> is <see cref="ToolTaskSupport.Required"/>
|
||||
/// (selected by <see cref="McpClientTaskExtensions.ListAgentToolsWithTaskSupportAsync"/>).
|
||||
/// As a defensive fallback, if the server still rejects the task-augmented call with
|
||||
/// <see cref="McpErrorCode.MethodNotFound"/> (e.g. because tool-level capabilities changed
|
||||
/// between <c>tools/list</c> and invocation), the wrapper transparently falls back to a
|
||||
/// non-augmented call through the inner <see cref="McpClientTool"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal sealed class TaskAwareMcpClientAIFunction : AIFunction
|
||||
{
|
||||
private readonly McpClient _client;
|
||||
private readonly McpClientTool _inner;
|
||||
private readonly McpTaskOptions _options;
|
||||
|
||||
internal TaskAwareMcpClientAIFunction(McpClient client, McpClientTool inner, McpTaskOptions options)
|
||||
{
|
||||
_ = Throw.IfNull(client);
|
||||
_ = Throw.IfNull(inner);
|
||||
_ = Throw.IfNull(options);
|
||||
|
||||
this._client = client;
|
||||
this._inner = inner;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => this._inner.Name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Description => this._inner.Description;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override JsonElement JsonSchema => this._inner.JsonSchema;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override JsonElement? ReturnJsonSchema => this._inner.ReturnJsonSchema;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override JsonSerializerOptions JsonSerializerOptions => this._inner.JsonSerializerOptions;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask<object?> InvokeCoreAsync(
|
||||
AIFunctionArguments arguments,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_ = Throw.IfNull(arguments);
|
||||
|
||||
McpTaskMetadata? metadata = null;
|
||||
if (this._options.DefaultTimeToLive is TimeSpan ttl)
|
||||
{
|
||||
metadata = new McpTaskMetadata { TimeToLive = ttl };
|
||||
}
|
||||
|
||||
McpTask task;
|
||||
try
|
||||
{
|
||||
task = await this._client.CallToolAsTaskAsync(
|
||||
this._inner.Name,
|
||||
arguments,
|
||||
taskMetadata: metadata,
|
||||
progress: null,
|
||||
options: null,
|
||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (McpProtocolException ex) when (ex.ErrorCode == McpErrorCode.MethodNotFound)
|
||||
{
|
||||
// Defensive fallback: the server's advertised TaskSupport indicated this tool
|
||||
// could be invoked as a task, but the server now rejects task augmentation for it
|
||||
// (e.g. capability changed between tools/list and invocation). Fall back to a
|
||||
// non-augmented call through the inner McpClientTool.
|
||||
return await this._inner.InvokeAsync(arguments, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await this.PollAndRetrieveResultAsync(task.TaskId, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<JsonElement> PollAndRetrieveResultAsync(string taskId, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
McpTask terminal = await this._client.PollTaskUntilCompleteAsync(taskId, options: null, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return terminal.Status switch
|
||||
{
|
||||
McpTaskStatus.Completed => await this._client.GetTaskResultAsync(taskId, options: null, cancellationToken).ConfigureAwait(false),
|
||||
McpTaskStatus.Cancelled => throw new OperationCanceledException(FormatTerminalStatusMessage(taskId, terminal)),
|
||||
_ => throw new InvalidOperationException(FormatTerminalStatusMessage(taskId, terminal)),// Failed (or any future non-terminal-but-unhandled status that the poll loop returns).
|
||||
};
|
||||
}
|
||||
catch (OperationCanceledException) when (this._options.CancelRemoteTaskOnLocalCancellation && cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
await this.TryCancelTaskAsync(taskId).ConfigureAwait(false);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatTerminalStatusMessage(string taskId, McpTask terminal)
|
||||
=> string.IsNullOrEmpty(terminal.StatusMessage)
|
||||
? $"MCP task '{taskId}' ended in terminal status '{terminal.Status}'."
|
||||
: $"MCP task '{taskId}' ended in terminal status '{terminal.Status}': {terminal.StatusMessage}";
|
||||
|
||||
private async Task TryCancelTaskAsync(string taskId)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
_ = await this._client.CancelTaskAsync(taskId, options: null, cts.Token).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Best-effort cancellation; do not mask the original cancellation reason.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal abstract class ActionTemplate : CodeTemplate, IModeledAction
|
||||
{
|
||||
public string Id { get; private set; } = string.Empty;
|
||||
|
||||
public string Name { get; private set; } = string.Empty;
|
||||
|
||||
public string ParentId { get; private set; } = string.Empty;
|
||||
|
||||
public bool UseAgentProvider { get; init; }
|
||||
|
||||
protected TAction Initialize<TAction>(TAction model) where TAction : DialogAction
|
||||
{
|
||||
this.Id = model.GetId();
|
||||
this.ParentId = model.GetParentId() ?? WorkflowActionVisitor.Steps.Root();
|
||||
this.Name = this.Id.FormatType();
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
-395
@@ -1,395 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
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", "18.0.0.0")]
|
||||
internal partial class AddConversationMessageTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <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, ResponseAgentProvider agentProvider) : ActionExe" +
|
||||
"cutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true);
|
||||
this.Write("\n if (string.IsNullOrWhiteSpace(conversationId))\n {\n thr" +
|
||||
"ow new DeclarativeActionException($\"Conversation identifier must be defined: {th" +
|
||||
"is.Id}\");\n }\n ChatMessage newMessage = new(ChatRole.");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(FormatEnum(this.Model.Role, RoleMap)));
|
||||
this.Write(", await this.GetContentAsync(context).ConfigureAwait(false)) { AdditionalProperti" +
|
||||
"es = this.GetMetadata() };\n newMessage = await agentProvider.CreateMessag" +
|
||||
"eAsync(conversationId, newMessage, cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
AssignVariable(this.Message, "newMessage");
|
||||
|
||||
this.Write("\n return default;\n }\n\n private async ValueTask<IList<AIContent>> Get" +
|
||||
"ContentAsync(IWorkflowContext context)\n {\n List<AIContent> content = [" +
|
||||
"];\n ");
|
||||
|
||||
int index = 0;
|
||||
foreach (AddConversationMessageContent content in this.Model.Content)
|
||||
{
|
||||
++index;
|
||||
EvaluateMessageTemplate(content.Value, $"contentValue{index}");
|
||||
AgentMessageContentType contentType = content.Type.Value;
|
||||
if (contentType == AgentMessageContentType.ImageUrl)
|
||||
{
|
||||
this.Write("\n content.Add(UriContent(contentValue");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(index));
|
||||
this.Write(", \"image/*\"));");
|
||||
|
||||
}
|
||||
else if (contentType == AgentMessageContentType.ImageFile)
|
||||
{
|
||||
this.Write("\n content.Add(new HostedFileContent(contentValue");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(index));
|
||||
this.Write("));");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write("\n content.Add(new TextContent(contentValue");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(index));
|
||||
this.Write("));");
|
||||
|
||||
}
|
||||
}
|
||||
this.Write("\n return content;\n }\n\n private AdditionalPropertiesDictionary? GetMe" +
|
||||
"tadata()\n {");
|
||||
|
||||
EvaluateRecordExpression<object>(this.Model.Metadata, "metadata");
|
||||
this.Write("\n\n if (metadata is null)\n {\n return null; \n }\n" +
|
||||
"\n return new AdditionalPropertiesDictionary(metadata);\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 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 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));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true); #>
|
||||
if (string.IsNullOrWhiteSpace(conversationId))
|
||||
{
|
||||
throw new DeclarativeActionException($"Conversation identifier must be defined: {this.Id}");
|
||||
}
|
||||
ChatMessage newMessage = new(ChatRole.<#= FormatEnum(this.Model.Role, RoleMap) #>, await this.GetContentAsync(context).ConfigureAwait(false)) { AdditionalProperties = this.GetMetadata() };
|
||||
newMessage = await agentProvider.CreateMessageAsync(conversationId, newMessage, cancellationToken).ConfigureAwait(false);<#
|
||||
AssignVariable(this.Message, "newMessage");
|
||||
#>
|
||||
return default;
|
||||
}
|
||||
|
||||
private async ValueTask<IList<AIContent>> GetContentAsync(IWorkflowContext context)
|
||||
{
|
||||
List<AIContent> content = [];
|
||||
<#
|
||||
int index = 0;
|
||||
foreach (AddConversationMessageContent content in this.Model.Content)
|
||||
{
|
||||
++index;
|
||||
EvaluateMessageTemplate(content.Value, $"contentValue{index}");
|
||||
AgentMessageContentType contentType = content.Type.Value;
|
||||
if (contentType == AgentMessageContentType.ImageUrl)
|
||||
{#>
|
||||
content.Add(UriContent(contentValue<#= index #>, "image/*"));<#
|
||||
}
|
||||
else if (contentType == AgentMessageContentType.ImageFile)
|
||||
{#>
|
||||
content.Add(new HostedFileContent(contentValue<#= index #>));<#
|
||||
}
|
||||
else
|
||||
{#>
|
||||
content.Add(new TextContent(contentValue<#= index #>));<#
|
||||
}
|
||||
}#>
|
||||
return content;
|
||||
}
|
||||
|
||||
private AdditionalPropertiesDictionary? GetMetadata()
|
||||
{<#
|
||||
EvaluateRecordExpression<object>(this.Model.Metadata, "metadata"); #>
|
||||
|
||||
if (metadata is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AdditionalPropertiesDictionary(metadata);
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class AddConversationMessageTemplate
|
||||
{
|
||||
public AddConversationMessageTemplate(AddConversationMessage model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Message = this.Model.Message?.Path;
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public AddConversationMessage Model { get; }
|
||||
|
||||
public PropertyPath? Message { get; }
|
||||
|
||||
public const string DefaultRole = nameof(ChatRole.User);
|
||||
|
||||
public static readonly FrozenDictionary<AgentMessageRoleWrapper, string> RoleMap =
|
||||
new Dictionary<AgentMessageRoleWrapper, string>()
|
||||
{
|
||||
[AgentMessageRoleWrapper.Get(AgentMessageRole.User)] = nameof(ChatRole.User),
|
||||
[AgentMessageRoleWrapper.Get(AgentMessageRole.Agent)] = nameof(ChatRole.Assistant),
|
||||
}.ToFrozenDictionary();
|
||||
}
|
||||
-221
@@ -1,221 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ClearAllVariablesTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Reset all the state for the targeted variable scope.\n/// </sum" +
|
||||
"mary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateEnumExpression<VariablesToClearWrapper, string>(this.Model.Variables, "targetScopeName", ScopeMap, isNullable: true);
|
||||
this.Write("\n await context.QueueClearScopeAsync(targetScopeName).ConfigureAwait(false" +
|
||||
");\n\n return default;\n }\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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateEnumExpression<VariablesToClearWrapper, string>(this.Model.Variables, "targetScopeName", ScopeMap, isNullable: true); #>
|
||||
await context.QueueClearScopeAsync(targetScopeName).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ClearAllVariablesTemplate
|
||||
{
|
||||
public ClearAllVariablesTemplate(ClearAllVariables model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public ClearAllVariables Model { get; }
|
||||
|
||||
public static readonly FrozenDictionary<VariablesToClearWrapper, string?> ScopeMap =
|
||||
new Dictionary<VariablesToClearWrapper, string?>()
|
||||
{
|
||||
[VariablesToClearWrapper.Get(VariablesToClear.AllGlobalVariables)] = VariableScopeNames.Global,
|
||||
[VariablesToClearWrapper.Get(VariablesToClear.ConversationScopedVariables)] = WorkflowFormulaState.DefaultScopeName,
|
||||
}.ToFrozenDictionary();
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal abstract class CodeTemplate
|
||||
{
|
||||
private bool _endsWithNewline;
|
||||
|
||||
private string CurrentIndentField { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public abstract string TransformText();
|
||||
|
||||
#region Object Model helpers
|
||||
|
||||
public static string VariableName(PropertyPath path) => Throw.IfNull(path.VariableName);
|
||||
public static string VariableScope(PropertyPath path) => Throw.IfNull(path.NamespaceAlias);
|
||||
|
||||
public static string FormatBoolValue(bool? value, bool defaultValue = false) =>
|
||||
value ?? defaultValue ? "true" : "false";
|
||||
|
||||
public static string FormatStringValue(string? value)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (value.Contains('\n') || value.Contains('\r'))
|
||||
{
|
||||
return @$"""""""{Environment.NewLine}{value}{Environment.NewLine}""""""";
|
||||
}
|
||||
|
||||
if (value.Contains('"') || value.Contains('\\'))
|
||||
{
|
||||
return @$"""""""{value}""""""";
|
||||
}
|
||||
|
||||
return @$"""{value}""";
|
||||
}
|
||||
|
||||
public static string FormatValue<TValue>(string? value)
|
||||
{
|
||||
if (typeof(TValue) == typeof(string))
|
||||
{
|
||||
return FormatStringValue(value);
|
||||
}
|
||||
|
||||
if (value is null)
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (typeof(TValue).IsEnum)
|
||||
{
|
||||
return $"{typeof(TValue).Name}.{value}";
|
||||
}
|
||||
|
||||
return $"{value}";
|
||||
}
|
||||
|
||||
public static string FormatDataValue(DataValue value) =>
|
||||
value switch
|
||||
{
|
||||
BlankDataValue => "null",
|
||||
BooleanDataValue booleanValue => FormatBoolValue(booleanValue.Value),
|
||||
FloatDataValue decimalValue => $"{decimalValue.Value}",
|
||||
NumberDataValue numberValue => $"{numberValue.Value}",
|
||||
DateDataValue dateValue => $"new DateTime({dateValue.Value.Ticks}, DateTimeKind.{dateValue.Value.Kind})",
|
||||
DateTimeDataValue datetimeValue => $"new DateTimeOffset({datetimeValue.Value.Ticks}, TimeSpan.FromTicks({datetimeValue.Value.Offset}))",
|
||||
TimeDataValue timeValue => $"TimeSpan.FromTicks({timeValue.Value.Ticks})",
|
||||
StringDataValue stringValue => FormatStringValue(stringValue.Value),
|
||||
OptionDataValue optionValue => @$"""{optionValue.Value}""",
|
||||
// Indenting is important here to make the generated code readable. Don't change it without testing the output.
|
||||
RecordDataValue recordValue =>
|
||||
$"""
|
||||
[
|
||||
{string.Join(",\n ", recordValue.Properties.Select(p => $"[\"{p.Key}\"] = {FormatDataValue(p.Value)}"))}
|
||||
]
|
||||
""",
|
||||
_ => throw new DeclarativeModelException($"Unable to format '{value.GetType().Name}'"),
|
||||
};
|
||||
|
||||
public static TTarget FormatEnum<TSource, TTarget>(TSource value, IDictionary<TSource, TTarget> map, TTarget? defaultValue = default)
|
||||
{
|
||||
if (map.TryGetValue(value, out TTarget? target))
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (defaultValue is null)
|
||||
{
|
||||
throw new DeclarativeModelException($"No default value suppied for '{typeof(TTarget).Name}'");
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static string GetTypeAlias<TValue>() => GetTypeAlias(typeof(TValue));
|
||||
|
||||
public static string GetTypeAlias(Type type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
Type t when t == typeof(bool) => "bool",
|
||||
Type t when t == typeof(byte) => "byte",
|
||||
Type t when t == typeof(sbyte) => "sbyte",
|
||||
Type t when t == typeof(char) => "char",
|
||||
Type t when t == typeof(decimal) => "decimal",
|
||||
Type t when t == typeof(double) => "double",
|
||||
Type t when t == typeof(float) => "float",
|
||||
Type t when t == typeof(int) => "int",
|
||||
Type t when t == typeof(uint) => "uint",
|
||||
Type t when t == typeof(long) => "long",
|
||||
Type t when t == typeof(ulong) => "ulong",
|
||||
Type t when t == typeof(nint) => "nint",
|
||||
Type t when t == typeof(nuint) => "nuint",
|
||||
Type t when t == typeof(short) => "short",
|
||||
Type t when t == typeof(ushort) => "ushort",
|
||||
Type t when t == typeof(string) => "string",
|
||||
Type t when t == typeof(object) => "object",
|
||||
_ => type.Name
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// The string builder that generation-time code is using to assemble generated output
|
||||
/// </summary>
|
||||
public StringBuilder GenerationEnvironment
|
||||
{
|
||||
get
|
||||
{
|
||||
return field ??= new StringBuilder();
|
||||
}
|
||||
set;
|
||||
}
|
||||
/// <summary>
|
||||
/// The error collection for the generation process
|
||||
/// </summary>
|
||||
public CompilerErrorCollection Errors => field ??= [];
|
||||
|
||||
/// <summary>
|
||||
/// A list of the lengths of each indent that was added with PushIndent
|
||||
/// </summary>
|
||||
private List<int> IndentLengths { get => field ??= []; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current indent we use when adding lines to the output
|
||||
/// </summary>
|
||||
public string CurrentIndent
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.CurrentIndentField;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Current transformation session
|
||||
/// </summary>
|
||||
public virtual IDictionary<string, object>? Session { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Transform-time helpers
|
||||
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string textToAppend)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textToAppend))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If we're starting off, or if the previous text ended with a newline,
|
||||
// we have to append the current indent first.
|
||||
if ((this.GenerationEnvironment.Length == 0)
|
||||
|| this._endsWithNewline)
|
||||
{
|
||||
this.GenerationEnvironment.Append(this.CurrentIndentField);
|
||||
this._endsWithNewline = false;
|
||||
}
|
||||
// Check if the current text ends with a newline
|
||||
if (textToAppend.EndsWith(Environment.NewLine, StringComparison.CurrentCulture))
|
||||
{
|
||||
this._endsWithNewline = true;
|
||||
}
|
||||
// This is an optimization. If the current indent is "", then we don't have to do any
|
||||
// of the more complex stuff further down.
|
||||
if (this.CurrentIndentField.Length == 0)
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend);
|
||||
return;
|
||||
}
|
||||
// Everywhere there is a newline in the text, add an indent after it
|
||||
textToAppend = textToAppend.Replace(Environment.NewLine, Environment.NewLine + this.CurrentIndentField);
|
||||
// If the text ends with a newline, then we should strip off the indent added at the very end
|
||||
// because the appropriate indent will be added when the next time Write() is called
|
||||
if (this._endsWithNewline)
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend, 0, textToAppend.Length - this.CurrentIndentField.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string textToAppend)
|
||||
{
|
||||
this.Write(textToAppend);
|
||||
this.GenerationEnvironment.AppendLine();
|
||||
this._endsWithNewline = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string format, params object[] args)
|
||||
{
|
||||
this.Write(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string format, params object[] args)
|
||||
{
|
||||
this.WriteLine(string.Format(CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise an error
|
||||
/// </summary>
|
||||
public void Error(string message)
|
||||
{
|
||||
CompilerError error = new()
|
||||
{
|
||||
ErrorText = message
|
||||
};
|
||||
this.Errors.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raise a warning
|
||||
/// </summary>
|
||||
public void Warning(string message)
|
||||
{
|
||||
CompilerError error = new()
|
||||
{
|
||||
ErrorText = message,
|
||||
IsWarning = true
|
||||
};
|
||||
error.ErrorText = message;
|
||||
error.IsWarning = true;
|
||||
this.Errors.Add(error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase the indent
|
||||
/// </summary>
|
||||
public void PushIndent(string indent)
|
||||
{
|
||||
if (indent is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(indent));
|
||||
}
|
||||
this.CurrentIndentField += indent;
|
||||
this.IndentLengths.Add(indent.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the last indent that was added with PushIndent
|
||||
/// </summary>
|
||||
public string PopIndent()
|
||||
{
|
||||
string returnValue = string.Empty;
|
||||
if (this.IndentLengths.Count > 0)
|
||||
{
|
||||
int indentLength = this.IndentLengths[this.IndentLengths.Count - 1];
|
||||
this.IndentLengths.RemoveAt(this.IndentLengths.Count - 1);
|
||||
if (indentLength > 0)
|
||||
{
|
||||
returnValue = this.CurrentIndentField.Substring(this.CurrentIndentField.Length - indentLength);
|
||||
this.CurrentIndentField = this.CurrentIndentField.Remove(this.CurrentIndentField.Length - indentLength);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove any indentation
|
||||
/// </summary>
|
||||
public void ClearIndent()
|
||||
{
|
||||
this.IndentLengths.Clear();
|
||||
this.CurrentIndentField = string.Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToString Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Utility class to produce culture-oriented representation of an object as a string.
|
||||
/// </summary>
|
||||
public sealed class ToStringInstanceHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
|
||||
/// </summary>
|
||||
#pragma warning disable CA1822 // Required to be non-static for use in generated code
|
||||
public string ToStringWithCulture(object objectToConvert) => $"{objectToConvert}";
|
||||
#pragma warning restore CA1822
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to produce culture-oriented representation of an object as a string
|
||||
/// </summary>
|
||||
public ToStringInstanceHelper ToStringHelper { get; } = new();
|
||||
|
||||
#endregion
|
||||
}
|
||||
-172
@@ -1,172 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ConditionGroupTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Conditional branching similar to an if / elseif / elseif / els" +
|
||||
"e chain.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
for (int index = 0; index < this.Model.Conditions.Length; ++index)
|
||||
{
|
||||
ConditionItem conditionItem = this.Model.Conditions[index];
|
||||
if (conditionItem.Condition is null)
|
||||
{
|
||||
continue; // Skip if no condition is defined
|
||||
}
|
||||
|
||||
EvaluateBoolExpression(conditionItem.Condition, $"condition{index}");
|
||||
this.Write("\n if (condition");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(index));
|
||||
this.Write(")\n {\n return \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(ConditionGroupExecutor.Steps.Item(this.Model, conditionItem)));
|
||||
this.Write("\";\n }\n ");
|
||||
|
||||
}
|
||||
|
||||
this.Write("\n return \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(ConditionGroupExecutor.Steps.Else(this.Model)));
|
||||
this.Write("\";\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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
for (int index = 0; index < this.Model.Conditions.Length; ++index)
|
||||
{
|
||||
ConditionItem conditionItem = this.Model.Conditions[index];
|
||||
if (conditionItem.Condition is null)
|
||||
{
|
||||
continue; // Skip if no condition is defined
|
||||
}
|
||||
|
||||
EvaluateBoolExpression(conditionItem.Condition, $"condition{index}");#>
|
||||
if (condition<#= index #>)
|
||||
{
|
||||
return "<#= ConditionGroupExecutor.Steps.Item(this.Model, conditionItem)#>";
|
||||
}
|
||||
<#
|
||||
}
|
||||
#>
|
||||
return "<#= ConditionGroupExecutor.Steps.Else(this.Model)#>";
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ConditionGroupTemplate
|
||||
{
|
||||
public ConditionGroupTemplate(ConditionGroup model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public ConditionGroup Model { get; }
|
||||
}
|
||||
-324
@@ -1,324 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class CopyConversationMessagesTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Copies one or more messages into the specified agent conversat" +
|
||||
"ion.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExe" +
|
||||
"cutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true);
|
||||
this.Write("\n if (string.IsNullOrWhiteSpace(conversationId))\n {\n thr" +
|
||||
"ow new DeclarativeActionException($\"Conversation identifier must be defined: {th" +
|
||||
"is.Id}\");\n }");
|
||||
|
||||
EvaluateValueExpression<ChatMessage[]>(this.Model.Messages, "messages");
|
||||
|
||||
this.Write(@"
|
||||
if (messages is not null)
|
||||
{
|
||||
foreach (ChatMessage message in messages)
|
||||
{
|
||||
await agentProvider.CreateMessageAsync(conversationId, message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}");
|
||||
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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true); #>
|
||||
if (string.IsNullOrWhiteSpace(conversationId))
|
||||
{
|
||||
throw new DeclarativeActionException($"Conversation identifier must be defined: {this.Id}");
|
||||
}<#
|
||||
EvaluateValueExpression<ChatMessage[]>(this.Model.Messages, "messages");
|
||||
#>
|
||||
if (messages is not null)
|
||||
{
|
||||
foreach (ChatMessage message in messages)
|
||||
{
|
||||
await agentProvider.CreateMessageAsync(conversationId, message, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class CopyConversationMessagesTemplate
|
||||
{
|
||||
public CopyConversationMessagesTemplate(CopyConversationMessages model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public CopyConversationMessages Model { get; }
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class CreateConversationTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Creates a new conversation and stores the identifier value to " +
|
||||
"the \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.ConversationId));
|
||||
this.Write("\" variable.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExe" +
|
||||
"cutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write(@""", session)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
AssignVariable(this.ConversationId, "conversationId");
|
||||
this.Write("\n await context.AddEventAsync(new ConversationUpdateEvent(conversationId))" +
|
||||
".ConfigureAwait(false);\n\n return default;\n }\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 ");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false);<#
|
||||
AssignVariable(this.ConversationId, "conversationId");#>
|
||||
await context.AddEventAsync(new ConversationUpdateEvent(conversationId)).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class CreateConversationTemplate
|
||||
{
|
||||
public CreateConversationTemplate(CreateConversation model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.ConversationId = Throw.IfNull(this.Model.ConversationId);
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public CreateConversation Model { get; }
|
||||
|
||||
public PropertyPath ConversationId { get; }
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class DefaultTemplate : ActionTemplate, IModeledAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\nDelegateExecutor ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.InstanceVariable));
|
||||
this.Write(" = new(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootVariable));
|
||||
this.Write(".Session");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Action is not null ? $", {this.Action}" : ""));
|
||||
this.Write(");\n");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate, IModeledAction" visibility="internal" linePragmas="false" #>
|
||||
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Interpreter" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
DelegateExecutor <#= this.InstanceVariable #> = new(id: "<#= this.Id #>", <#= this.RootVariable #>.Session<#= this.Action is not null ? $", {this.Action}" : "" #>);
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class DefaultTemplate
|
||||
{
|
||||
public DefaultTemplate(DialogAction model, string rootId, string? action = null)
|
||||
{
|
||||
this.Initialize(model);
|
||||
this.Action = action;
|
||||
this.InstanceVariable = this.Id.FormatName();
|
||||
this.RootVariable = rootId.FormatName();
|
||||
}
|
||||
|
||||
public string? Action { get; }
|
||||
public string InstanceVariable { get; }
|
||||
public string RootVariable { get; }
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class EdgeTemplate : CodeTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
if (this.Condition is not null)
|
||||
{
|
||||
this.Write("\n builder.AddEdge(");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.SourceId));
|
||||
this.Write(", ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.TargetId));
|
||||
this.Write(", (object? result) => ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Condition));
|
||||
this.Write(");");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write("\n builder.AddEdge(");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.SourceId));
|
||||
this.Write(", ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.TargetId));
|
||||
this.Write(");");
|
||||
|
||||
}
|
||||
this.Write("\n");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<#@ template language="C#" inherits="CodeTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<# if (this.Condition is not null)
|
||||
{#>
|
||||
builder.AddEdge(<#= this.SourceId #>, <#= this.TargetId #>, (object? result) => <#= this.Condition #>);<#
|
||||
}
|
||||
else
|
||||
{#>
|
||||
builder.AddEdge(<#= this.SourceId #>, <#= this.TargetId #>);<#
|
||||
} #>
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class EdgeTemplate
|
||||
{
|
||||
public EdgeTemplate(string sourceId, string targetId, string? condition = null)
|
||||
{
|
||||
this.SourceId = sourceId.FormatName();
|
||||
this.TargetId = targetId.FormatName();
|
||||
this.Condition = condition;
|
||||
}
|
||||
|
||||
public string SourceId { get; }
|
||||
public string TargetId { get; }
|
||||
public string? Condition { get; }
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class EditTableV2Template : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Modify items in a list\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {\n return default;\n }\n}");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
/// <summary>
|
||||
/// Modify items in a list
|
||||
/// </summary>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class EditTableV2Template
|
||||
{
|
||||
public EditTableV2Template(EditTableV2 model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public EditTableV2 Model { get; }
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class EmptyTemplate : CodeTemplate, IModeledAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\nDelegateExecutor ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.InstanceVariable));
|
||||
this.Write(" = new(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootVariable));
|
||||
this.Write(".Session");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Action is not null ? $", {this.Action}" : ""));
|
||||
this.Write(");\n");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
<#@ template language="C#" inherits="CodeTemplate, IModeledAction" visibility="internal" linePragmas="false" #>
|
||||
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Interpreter" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
DelegateExecutor <#= this.InstanceVariable #> = new(id: "<#= this.Id #>", <#= this.RootVariable #>.Session<#= this.Action is not null ? $", {this.Action}" : "" #>);
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class EmptyTemplate
|
||||
{
|
||||
public EmptyTemplate(string actionId, string rootId, string? action = null)
|
||||
{
|
||||
this.Id = actionId;
|
||||
this.Name = this.Id.FormatType();
|
||||
this.InstanceVariable = this.Id.FormatName();
|
||||
this.RootVariable = rootId.FormatName();
|
||||
this.Action = action;
|
||||
}
|
||||
|
||||
public string Id { get; }
|
||||
public string Name { get; }
|
||||
public string InstanceVariable { get; }
|
||||
public string RootVariable { get; }
|
||||
public string? Action { get; }
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ForeachTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Loops over a list assignign the loop variable to \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Value));
|
||||
this.Write("\" variable.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write(@""", session)
|
||||
{
|
||||
private int _index;
|
||||
private object[] _values = [];
|
||||
|
||||
public bool HasValue { get; private set; }
|
||||
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
this._index = 0;");
|
||||
|
||||
|
||||
EvaluateValueExpression(this.Model.Items, "evaluatedValue");
|
||||
this.Write(@"
|
||||
|
||||
if (evaluatedValue == null)
|
||||
{
|
||||
this._values = [];
|
||||
this.HasValue = false;
|
||||
}
|
||||
else
|
||||
if (evaluatedValue is IEnumerable evaluatedList)
|
||||
{
|
||||
this._values = [.. evaluatedList];
|
||||
}
|
||||
else
|
||||
{
|
||||
this._values = [evaluatedValue];
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public async ValueTask TakeNextAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.HasValue = this._index < this._values.Length)
|
||||
{
|
||||
object value = this._values[this._index];
|
||||
");
|
||||
|
||||
AssignVariable(this.Value, "value", tightFormat: true);
|
||||
|
||||
if (this.Index is not null)
|
||||
{
|
||||
AssignVariable(this.Index, "this._index", tightFormat: true);
|
||||
}
|
||||
|
||||
this.Write(@"
|
||||
|
||||
this._index++;
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask ResetAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{");
|
||||
|
||||
AssignVariable(this.Value, "UnassignedValue.Instance", tightFormat: true);
|
||||
|
||||
if (this.Index is not null)
|
||||
{
|
||||
AssignVariable(this.Index, "UnassignedValue.Instance", tightFormat: true);
|
||||
}
|
||||
|
||||
this.Write("\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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
private int _index;
|
||||
private object[] _values = [];
|
||||
|
||||
public bool HasValue { get; private set; }
|
||||
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
this._index = 0;<#
|
||||
|
||||
EvaluateValueExpression(this.Model.Items, "evaluatedValue");#>
|
||||
|
||||
if (evaluatedValue == null)
|
||||
{
|
||||
this._values = [];
|
||||
this.HasValue = false;
|
||||
}
|
||||
else
|
||||
if (evaluatedValue is IEnumerable evaluatedList)
|
||||
{
|
||||
this._values = [.. evaluatedList];
|
||||
}
|
||||
else
|
||||
{
|
||||
this._values = [evaluatedValue];
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public async ValueTask TakeNextAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.HasValue = this._index < this._values.Length)
|
||||
{
|
||||
object value = this._values[this._index];
|
||||
<#
|
||||
AssignVariable(this.Value, "value", tightFormat: true);
|
||||
|
||||
if (this.Index is not null)
|
||||
{
|
||||
AssignVariable(this.Index, "this._index", tightFormat: true);
|
||||
}
|
||||
#>
|
||||
|
||||
this._index++;
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask ResetAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
AssignVariable(this.Value, "UnassignedValue.Instance", tightFormat: true);
|
||||
|
||||
if (this.Index is not null)
|
||||
{
|
||||
AssignVariable(this.Index, "UnassignedValue.Instance", tightFormat: true);
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ForeachTemplate
|
||||
{
|
||||
public ForeachTemplate(Foreach model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Index = this.Model.Index?.Path;
|
||||
this.Value = Throw.IfNull(this.Model.Value);
|
||||
}
|
||||
|
||||
public Foreach Model { get; }
|
||||
public PropertyPath? Index { get; }
|
||||
public PropertyPath Value { get; }
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class InstanceTemplate : CodeTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.ExecutorType));
|
||||
this.Write("Executor ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.InstanceVariable));
|
||||
this.Write(" = new(");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootVariable));
|
||||
this.Write(".Session");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.HasProvider ? ", options.AgentProvider" : ""));
|
||||
this.Write(");");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<#@ template language="C#" inherits="CodeTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#= this.ExecutorType #>Executor <#= this.InstanceVariable #> = new(<#= this.RootVariable #>.Session<#= this.HasProvider ? ", options.AgentProvider" : "" #>);
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class InstanceTemplate
|
||||
{
|
||||
public InstanceTemplate(string executorId, string rootId, bool hasProvider = false)
|
||||
{
|
||||
this.InstanceVariable = executorId.FormatName();
|
||||
this.ExecutorType = executorId.FormatType();
|
||||
this.RootVariable = rootId.FormatName();
|
||||
this.HasProvider = hasProvider;
|
||||
}
|
||||
|
||||
public string InstanceVariable { get; }
|
||||
public string ExecutorType { get; }
|
||||
public string RootVariable { get; }
|
||||
public bool HasProvider { get; }
|
||||
}
|
||||
-415
@@ -1,415 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class InvokeAzureAgentTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <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));
|
||||
this.Write("Executor(FormulaSession session, ResponseAgentProvider agentProvider) : AgentExec" +
|
||||
"utor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session, agentProvider)\n{\n // <inheritdoc />\n protected override async V" +
|
||||
"alueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cance" +
|
||||
"llationToken)\n {");
|
||||
|
||||
EvaluateStringExpression(this.Model.Agent.Name, "agentName", isNullable: true);
|
||||
this.Write("\n\n if (string.IsNullOrWhiteSpace(agentName))\n {\n throw n" +
|
||||
"ew DeclarativeActionException($\"Agent name must be defined: {this.Id}\");\n " +
|
||||
" }\n ");
|
||||
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true);
|
||||
EvaluateBoolExpression(this.Model.Output?.AutoSend, "autoSend", defaultValue: true);
|
||||
EvaluateListExpression<ChatMessage>(this.Model.Input?.Messages, "inputMessages");
|
||||
this.Write(@"
|
||||
|
||||
AgentResponse agentResponse =
|
||||
await InvokeAgentAsync(
|
||||
context,
|
||||
agentName,
|
||||
conversationId,
|
||||
autoSend,
|
||||
inputMessages,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (autoSend)
|
||||
{
|
||||
await context.AddEventAsync(new AgentResponseEvent(this.Id, agentResponse)).ConfigureAwait(false);
|
||||
}
|
||||
");
|
||||
|
||||
AssignVariable(this.Messages, "agentResponse.Messages");
|
||||
this.Write("\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 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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : AgentExecutor(id: "<#= this.Id #>", session, agentProvider)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateStringExpression(this.Model.Agent.Name, "agentName", isNullable: true);#>
|
||||
|
||||
if (string.IsNullOrWhiteSpace(agentName))
|
||||
{
|
||||
throw new DeclarativeActionException($"Agent name must be defined: {this.Id}");
|
||||
}
|
||||
<#
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId", isNullable: true);
|
||||
EvaluateBoolExpression(this.Model.Output?.AutoSend, "autoSend", defaultValue: true);
|
||||
EvaluateListExpression<ChatMessage>(this.Model.Input?.Messages, "inputMessages");#>
|
||||
|
||||
AgentResponse agentResponse =
|
||||
await InvokeAgentAsync(
|
||||
context,
|
||||
agentName,
|
||||
conversationId,
|
||||
autoSend,
|
||||
inputMessages,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (autoSend)
|
||||
{
|
||||
await context.AddEventAsync(new AgentResponseEvent(this.Id, agentResponse)).ConfigureAwait(false);
|
||||
}
|
||||
<#
|
||||
AssignVariable(this.Messages, "agentResponse.Messages"); #>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class InvokeAzureAgentTemplate
|
||||
{
|
||||
public InvokeAzureAgentTemplate(InvokeAzureAgent model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Messages = this.Model.Output?.Messages?.Path;
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public InvokeAzureAgent Model { get; }
|
||||
|
||||
public PropertyPath? Messages { get; }
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ParseValueTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Parses a string or untyped value to the provided data type. Wh" +
|
||||
"en the input is a string, it will be treated as JSON.\n/// </summary>\ninternal se" +
|
||||
"aled class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" { \n VariableType targetType = ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.GetVariableType()));
|
||||
this.Write(";");
|
||||
|
||||
if (this.Model.Value.IsVariableReference && this.Model.Value.VariableReference.SegmentCount == 2)
|
||||
{
|
||||
this.Write("\n object? parsedValue = await context.ConvertValueAsync(targetType, key: \"" +
|
||||
"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Value.VariableReference.VariableName));
|
||||
this.Write("\", scopeName: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Value.VariableReference.NamespaceAlias));
|
||||
this.Write("\", cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
}
|
||||
else if (this.Model.Value.IsVariableReference)
|
||||
{
|
||||
this.Write("\n object? parsedValue = await context.ConvertValueAsync(targetType, ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(this.Model.Value.VariableReference.ToString())));
|
||||
this.Write(", cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Write("\n object? parsedValue = await context.ConvertValueAsync(targetType, ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(FormatStringValue(this.Model.Value.ExpressionText)));
|
||||
this.Write(", cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
}
|
||||
AssignVariable(this.Variable, "parsedValue");
|
||||
this.Write("\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 ");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
VariableType targetType = <#= this.GetVariableType() #>;<#
|
||||
if (this.Model.Value.IsVariableReference && this.Model.Value.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
object? parsedValue = await context.ConvertValueAsync(targetType, key: "<#= this.Model.Value.VariableReference.VariableName #>", scopeName: "<#= this.Model.Value.VariableReference.NamespaceAlias #>", cancellationToken).ConfigureAwait(false);<#
|
||||
}
|
||||
else if (this.Model.Value.IsVariableReference)
|
||||
{#>
|
||||
object? parsedValue = await context.ConvertValueAsync(targetType, <#= FormatStringValue(this.Model.Value.VariableReference.ToString()) #>, cancellationToken).ConfigureAwait(false);<#
|
||||
}
|
||||
else
|
||||
{#>
|
||||
object? parsedValue = await context.ConvertValueAsync(targetType, <#= FormatStringValue(this.Model.Value.ExpressionText) #>, cancellationToken).ConfigureAwait(false);<#
|
||||
}
|
||||
AssignVariable(this.Variable, "parsedValue"); #>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ParseValueTemplate
|
||||
{
|
||||
public ParseValueTemplate(ParseValue model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Variable = Throw.IfNull(this.Model.Variable);
|
||||
}
|
||||
|
||||
public ParseValue Model { get; }
|
||||
public PropertyPath Variable { get; }
|
||||
|
||||
private string GetVariableType()
|
||||
{
|
||||
return GetVariableType(this.Model.ValueType);
|
||||
|
||||
static string GetVariableType(DataType? dataType) =>
|
||||
dataType switch
|
||||
{
|
||||
null => "null",
|
||||
StringDataType => "typeof(string)",
|
||||
BooleanDataType => "typeof(bool)",
|
||||
FloatDataType => "typeof(double)",
|
||||
NumberDataType => "typeof(decimal)",
|
||||
DateTimeDataType => "typeof(DateTime)",
|
||||
DateDataType => "typeof(DateTime)",
|
||||
TimeDataType => "typeof(TimeSpan)",
|
||||
RecordDataType recordType => $"\nVariableType.Record(\n{string.Join(",\n ", recordType.Properties.Select(property => @$"( ""{property.Key}"", {GetVariableType(property.Value.Type)} )"))})",
|
||||
TableDataType tableType => $"\nVariableType.Record(\n{string.Join(",\n ", tableType.Properties.Select(property => @$"( ""{property.Key}"", {GetVariableType(property.Value.Type)} )"))})",
|
||||
_ => throw new DeclarativeModelException($"Unsupported data type: {dataType}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ProviderTemplate : CodeTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write(@"
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
#pragma warning disable IDE0005 // Extra using directive is ok.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Kit;
|
||||
using Microsoft.Extensions.AI;
|
||||
");
|
||||
|
||||
if (this.Namespace is not null)
|
||||
{
|
||||
this.Write("\nnamespace ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Namespace));
|
||||
this.Write(";\n");
|
||||
|
||||
}
|
||||
|
||||
this.Write(@"
|
||||
/// <summary>
|
||||
/// This class provides a factory method to create a <see cref=""Workflow"" /> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The workflow defined here was generated from a declarative workflow definition.
|
||||
/// Declarative workflows utilize Power FX for defining conditions and expressions.
|
||||
/// To learn more about Power FX, see:
|
||||
/// https://learn.microsoft.com/power-platform/power-fx/formula-reference-copilot-studio
|
||||
/// </remarks>
|
||||
public static class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Prefix ?? string.Empty));
|
||||
this.Write("WorkflowProvider\n{");
|
||||
|
||||
foreach (string executor in ByLine(this.Executors, formatGroup: true))
|
||||
{
|
||||
this.Write("\n ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(executor));
|
||||
|
||||
}
|
||||
|
||||
this.Write(@"
|
||||
public static Workflow CreateWorkflow<TInput>(
|
||||
DeclarativeWorkflowOptions options,
|
||||
Func<TInput, ChatMessage>? inputTransform = null)
|
||||
where TInput : notnull
|
||||
{
|
||||
// Create root executor to initialize the workflow.
|
||||
inputTransform ??= (message) => DeclarativeWorkflowBuilder.DefaultTransform(message);
|
||||
");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootExecutorType));
|
||||
this.Write("Executor<TInput> ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootInstance));
|
||||
this.Write(" = new(options, inputTransform);");
|
||||
|
||||
|
||||
// Create executor instances
|
||||
foreach (string instance in ByLine(this.Instances))
|
||||
{
|
||||
this.Write("\n ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(instance));
|
||||
|
||||
}
|
||||
this.Write("\n\n // Define the workflow builder\n WorkflowBuilder builder = new(");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.RootInstance));
|
||||
this.Write(");\n\n // Connect executors");
|
||||
|
||||
foreach (string edge in ByLine(this.Edges))
|
||||
{
|
||||
this.Write("\n ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(edge));
|
||||
|
||||
}
|
||||
|
||||
this.Write("\n\n // Build the workflow\n return builder.Build(validateOrphans: fal" +
|
||||
"se);\n }\n}\n");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<#@ template language="C#" inherits="CodeTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#nullable enable
|
||||
#pragma warning disable IDE0005 // Extra using directive is ok.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Kit;
|
||||
using Microsoft.Extensions.AI;
|
||||
<#
|
||||
if (this.Namespace is not null)
|
||||
{#>
|
||||
namespace <#= this.Namespace #>;
|
||||
<#
|
||||
}
|
||||
#>
|
||||
/// <summary>
|
||||
/// This class provides a factory method to create a <see cref="Workflow" /> instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The workflow defined here was generated from a declarative workflow definition.
|
||||
/// Declarative workflows utilize Power FX for defining conditions and expressions.
|
||||
/// To learn more about Power FX, see:
|
||||
/// https://learn.microsoft.com/power-platform/power-fx/formula-reference-copilot-studio
|
||||
/// </remarks>
|
||||
public static class <#= this.Prefix ?? string.Empty #>WorkflowProvider
|
||||
{<#
|
||||
foreach (string executor in ByLine(this.Executors, formatGroup: true))
|
||||
{ #>
|
||||
<#= executor #><#
|
||||
}
|
||||
#>
|
||||
public static Workflow CreateWorkflow<TInput>(
|
||||
DeclarativeWorkflowOptions options,
|
||||
Func<TInput, ChatMessage>? inputTransform = null)
|
||||
where TInput : notnull
|
||||
{
|
||||
// Create root executor to initialize the workflow.
|
||||
inputTransform ??= (message) => DeclarativeWorkflowBuilder.DefaultTransform(message);
|
||||
<#= this.RootExecutorType #>Executor<TInput> <#= this.RootInstance #> = new(options, inputTransform);<#
|
||||
|
||||
// Create executor instances
|
||||
foreach (string instance in ByLine(this.Instances))
|
||||
{ #>
|
||||
<#= instance #><#
|
||||
}#>
|
||||
|
||||
// Define the workflow builder
|
||||
WorkflowBuilder builder = new(<#= this.RootInstance #>);
|
||||
|
||||
// Connect executors<#
|
||||
foreach (string edge in ByLine(this.Edges))
|
||||
{ #>
|
||||
<#= edge #><#
|
||||
}
|
||||
#>
|
||||
|
||||
// Build the workflow
|
||||
return builder.Build(validateOrphans: false);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ProviderTemplate
|
||||
{
|
||||
public ProviderTemplate(
|
||||
string workflowId,
|
||||
IEnumerable<string> executors,
|
||||
IEnumerable<string> instances,
|
||||
IEnumerable<string> edges)
|
||||
{
|
||||
this.Executors = executors;
|
||||
this.Instances = instances;
|
||||
this.Edges = edges;
|
||||
this.RootInstance = workflowId.FormatName();
|
||||
this.RootExecutorType = workflowId.FormatType();
|
||||
}
|
||||
|
||||
public string? Namespace { get; init; }
|
||||
public string? Prefix { get; init; }
|
||||
|
||||
public string RootInstance { get; }
|
||||
public string RootExecutorType { get; }
|
||||
|
||||
public IEnumerable<string> Executors { get; }
|
||||
public IEnumerable<string> Instances { get; }
|
||||
public IEnumerable<string> Edges { get; }
|
||||
|
||||
public static IEnumerable<string> ByLine(IEnumerable<string> templates, bool formatGroup = false)
|
||||
{
|
||||
foreach (string template in templates)
|
||||
{
|
||||
foreach (string line in template.ByLine())
|
||||
{
|
||||
yield return line;
|
||||
}
|
||||
|
||||
if (formatGroup)
|
||||
{
|
||||
yield return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class QuestionTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Request input.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {\n return default;\n }\n}");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
/// <summary>
|
||||
/// Request input.
|
||||
/// </summary>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class QuestionTemplate
|
||||
{
|
||||
public QuestionTemplate(Question model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public Question Model { get; }
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class ResetVariableTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Resets the value of the \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Variable));
|
||||
this.Write("\" variable, potentially causing re-evaluation \n/// of the default value, question" +
|
||||
" or action that provides the value to this variable.\n/// </summary>\ninternal sea" +
|
||||
"led class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n protected override async ValueTask<object?> ExecuteAsync(IWorkf" +
|
||||
"lowContext context, CancellationToken cancellationToken)\n {");
|
||||
|
||||
AssignVariable(this.Variable, "UnassignedValue.Instance");
|
||||
this.Write("\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 ");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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.
|
||||
/// </summary>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
AssignVariable(this.Variable, "UnassignedValue.Instance"); #>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class ResetVariableTemplate
|
||||
{
|
||||
public ResetVariableTemplate(ResetVariable model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Variable = Throw.IfNull(this.Model.Variable);
|
||||
}
|
||||
|
||||
public ResetVariable Model { get; }
|
||||
|
||||
public PropertyPath Variable { get; }
|
||||
}
|
||||
-310
@@ -1,310 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class RetrieveConversationMessageTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Retrieves a list of messages from an agent conversation.\n/// <" +
|
||||
"/summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExe" +
|
||||
"cutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId");
|
||||
EvaluateStringExpression(this.Model.MessageId, "messageId");
|
||||
this.Write("\n ChatMessage message = await agentProvider.GetMessageAsync(conversationId" +
|
||||
", messageId, cancellationToken).ConfigureAwait(false);");
|
||||
|
||||
AssignVariable(this.Model.Message, "message");
|
||||
|
||||
this.Write("\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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId");
|
||||
EvaluateStringExpression(this.Model.MessageId, "messageId"); #>
|
||||
ChatMessage message = await agentProvider.GetMessageAsync(conversationId, messageId, cancellationToken).ConfigureAwait(false);<#
|
||||
AssignVariable(this.Model.Message, "message");
|
||||
#>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class RetrieveConversationMessageTemplate
|
||||
{
|
||||
public RetrieveConversationMessageTemplate(RetrieveConversationMessage model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public RetrieveConversationMessage Model { get; }
|
||||
}
|
||||
-584
@@ -1,584 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
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", "18.0.0.0")]
|
||||
internal partial class RetrieveConversationMessagesTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Retrieves a specific message from an agent conversation.\n/// <" +
|
||||
"/summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExe" +
|
||||
"cutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId");
|
||||
EvaluateIntExpression(this.Model.Limit, "limit");
|
||||
EvaluateStringExpression(this.Model.MessageAfter, "after", isNullable: true);
|
||||
EvaluateStringExpression(this.Model.MessageBefore, "before", isNullable: true);
|
||||
EvaluateEnumExpression<AgentMessageSortOrderWrapper, bool>(this.Model.SortOrder, "newestFirst", SortMap, defaultValue: DefaultSort);
|
||||
this.Write(@"
|
||||
IAsyncEnumerable<ChatMessage> messagesResult =
|
||||
agentProvider.GetMessagesAsync(
|
||||
conversationId,
|
||||
limit,
|
||||
after,
|
||||
before,
|
||||
newestFirst,
|
||||
cancellationToken);
|
||||
List<ChatMessage> messages = [];
|
||||
await foreach (ChatMessage message in messagesResult.ConfigureAwait(false))
|
||||
{
|
||||
messages.Add(message);
|
||||
}");
|
||||
|
||||
AssignVariable(this.Model.Messages, "messages");
|
||||
|
||||
this.Write("\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 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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session, ResponseAgentProvider agentProvider) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateStringExpression(this.Model.ConversationId, "conversationId");
|
||||
EvaluateIntExpression(this.Model.Limit, "limit");
|
||||
EvaluateStringExpression(this.Model.MessageAfter, "after", isNullable: true);
|
||||
EvaluateStringExpression(this.Model.MessageBefore, "before", isNullable: true);
|
||||
EvaluateEnumExpression<AgentMessageSortOrderWrapper, bool>(this.Model.SortOrder, "newestFirst", SortMap, defaultValue: DefaultSort); #>
|
||||
IAsyncEnumerable<ChatMessage> messagesResult =
|
||||
agentProvider.GetMessagesAsync(
|
||||
conversationId,
|
||||
limit,
|
||||
after,
|
||||
before,
|
||||
newestFirst,
|
||||
cancellationToken);
|
||||
List<ChatMessage> messages = [];
|
||||
await foreach (ChatMessage message in messagesResult.ConfigureAwait(false))
|
||||
{
|
||||
messages.Add(message);
|
||||
}<#
|
||||
AssignVariable(this.Model.Messages, "messages");
|
||||
#>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class RetrieveConversationMessagesTemplate
|
||||
{
|
||||
public RetrieveConversationMessagesTemplate(RetrieveConversationMessages model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.UseAgentProvider = true;
|
||||
}
|
||||
|
||||
public RetrieveConversationMessages Model { get; }
|
||||
|
||||
public const string DefaultSort = "false";
|
||||
|
||||
public static readonly FrozenDictionary<AgentMessageSortOrderWrapper, string> SortMap =
|
||||
new Dictionary<AgentMessageSortOrderWrapper, string>()
|
||||
{
|
||||
[AgentMessageSortOrderWrapper.Get(AgentMessageSortOrder.NewestFirst)] = "true",
|
||||
[AgentMessageSortOrderWrapper.Get(AgentMessageSortOrder.OldestFirst)] = "false",
|
||||
}.ToFrozenDictionary();
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class RootTemplate : CodeTemplate, IModeledAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// The root executor for a declarative workflow.\n/// </summary>\ni" +
|
||||
"nternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.TypeName));
|
||||
this.Write("Executor<TInput>(\n DeclarativeWorkflowOptions options,\n Func<TInput, ChatMe" +
|
||||
"ssage> inputTransform) :\n RootExecutor<TInput>(\"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", options, inputTransform)\n where TInput : notnull\n{\n protected override a" +
|
||||
"sync ValueTask ExecuteAsync(TInput message, IWorkflowContext context, Cancellati" +
|
||||
"onToken cancellationToken)\n {");
|
||||
|
||||
if (this.TypeInfo.EnvironmentVariables.Count > 0)
|
||||
{
|
||||
this.Write("\n // Set environment variables\n await this.InitializeEnvironmentAsy" +
|
||||
"nc(\n context,");
|
||||
|
||||
int index = this.TypeInfo.EnvironmentVariables.Count - 1;
|
||||
foreach (string variableName in this.TypeInfo.EnvironmentVariables)
|
||||
{
|
||||
this.Write("\n \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(variableName));
|
||||
this.Write("\"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(index > 0 ? "," : ""));
|
||||
|
||||
--index;
|
||||
}
|
||||
this.Write(").ConfigureAwait(false);\n");
|
||||
}
|
||||
|
||||
if (this.TypeInfo.UserVariables.Count > 0)
|
||||
{
|
||||
|
||||
this.Write("\n // Initialize variables");
|
||||
|
||||
foreach (VariableInformationDiagnostic variableInfo in this.TypeInfo.UserVariables)
|
||||
{
|
||||
this.Write("\n await context.QueueStateUpdateAsync(\"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(variableInfo.Path.VariableName));
|
||||
this.Write("\", UnassignedValue.Instance, \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(variableInfo.Path.NamespaceAlias));
|
||||
this.Write("\").ConfigureAwait(false);");
|
||||
|
||||
}
|
||||
}
|
||||
this.Write("\n }\n}\n");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<#@ template language="C#" inherits="CodeTemplate, IModeledAction" visibility="internal" linePragmas="false" #>
|
||||
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Extensions" #>
|
||||
<#@ import namespace="Microsoft.Agents.AI.Workflows.Declarative.Interpreter" #>
|
||||
<#@ import namespace="Microsoft.Agents.ObjectModel" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
/// <summary>
|
||||
/// The root executor for a declarative workflow.
|
||||
/// </summary>
|
||||
internal sealed class <#= this.TypeName #>Executor<TInput>(
|
||||
DeclarativeWorkflowOptions options,
|
||||
Func<TInput, ChatMessage> inputTransform) :
|
||||
RootExecutor<TInput>("<#= this.Id #>", options, inputTransform)
|
||||
where TInput : notnull
|
||||
{
|
||||
protected override async ValueTask ExecuteAsync(TInput message, IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
if (this.TypeInfo.EnvironmentVariables.Count > 0)
|
||||
{ #>
|
||||
// Set environment variables
|
||||
await this.InitializeEnvironmentAsync(
|
||||
context,<#
|
||||
int index = this.TypeInfo.EnvironmentVariables.Count - 1;
|
||||
foreach (string variableName in this.TypeInfo.EnvironmentVariables)
|
||||
{#>
|
||||
"<#= variableName #>"<#= index > 0 ? "," : "" #><#
|
||||
--index;
|
||||
}#>).ConfigureAwait(false);
|
||||
<#}
|
||||
|
||||
if (this.TypeInfo.UserVariables.Count > 0)
|
||||
{
|
||||
#>
|
||||
// Initialize variables<#
|
||||
foreach (VariableInformationDiagnostic variableInfo in this.TypeInfo.UserVariables)
|
||||
{#>
|
||||
await context.QueueStateUpdateAsync("<#= variableInfo.Path.VariableName #>", UnassignedValue.Instance, "<#= variableInfo.Path.NamespaceAlias #>").ConfigureAwait(false);<#
|
||||
}
|
||||
}#>
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.PowerFx;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class RootTemplate
|
||||
{
|
||||
internal RootTemplate(
|
||||
string workflowId,
|
||||
WorkflowTypeInfo typeInfo)
|
||||
{
|
||||
this.Id = workflowId;
|
||||
this.TypeInfo = typeInfo;
|
||||
this.TypeName = workflowId.FormatType();
|
||||
}
|
||||
|
||||
public string Id { get; }
|
||||
public WorkflowTypeInfo TypeInfo { get; }
|
||||
public string TypeName { get; }
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
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", "18.0.0.0")]
|
||||
internal partial class SendActivityTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Formats a message template and sends an activity event.\n/// </" +
|
||||
"summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" { ");
|
||||
|
||||
if (this.Model.Activity is MessageActivityTemplate messageActivity)
|
||||
{
|
||||
this.Write("\n string activityText = \n await context.FormatTemplateAsync( ");
|
||||
|
||||
foreach (TemplateLine line in messageActivity.Text)
|
||||
{
|
||||
this.Write("\n \"\"\"");
|
||||
|
||||
foreach (string text in line.ToTemplateString().ByLine())
|
||||
{
|
||||
this.Write("\n ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(text));
|
||||
|
||||
}
|
||||
this.Write("\n \"\"\"");
|
||||
|
||||
}
|
||||
|
||||
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 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,36 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{ <#
|
||||
if (this.Model.Activity is MessageActivityTemplate messageActivity)
|
||||
{ #>
|
||||
string activityText =
|
||||
await context.FormatTemplateAsync( <#
|
||||
foreach (TemplateLine line in messageActivity.Text)
|
||||
{ #>
|
||||
"""<#
|
||||
foreach (string text in line.ToTemplateString().ByLine())
|
||||
{ #>
|
||||
<#= text #><#
|
||||
} #>
|
||||
"""<#
|
||||
}
|
||||
#>
|
||||
);
|
||||
AgentResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]);
|
||||
await context.AddEventAsync(new AgentResponseEvent(this.Id, response)).ConfigureAwait(false);<#
|
||||
} #>
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class SendActivityTemplate
|
||||
{
|
||||
public SendActivityTemplate(SendActivity model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public SendActivity Model { get; }
|
||||
}
|
||||
-195
@@ -1,195 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class SetMultipleVariablesTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Assigns an evaluated expression, other variable, or literal va" +
|
||||
"lue to one or more variables.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
int index = 0;
|
||||
foreach (var assignment in this.Model.Assignments)
|
||||
{
|
||||
// Separate assigments with a blank line for readability
|
||||
if (index > 0)
|
||||
{
|
||||
this.Write("\n ");
|
||||
|
||||
}
|
||||
++index;
|
||||
EvaluateValueExpression(assignment.Value, $"evaluatedValue{index}");
|
||||
AssignVariable(assignment.Variable, $"evaluatedValue{index}");
|
||||
}
|
||||
|
||||
this.Write("\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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<# int index = 0;
|
||||
foreach (var assignment in this.Model.Assignments)
|
||||
{
|
||||
// Separate assigments with a blank line for readability
|
||||
if (index > 0)
|
||||
{#>
|
||||
<#
|
||||
}
|
||||
++index;
|
||||
EvaluateValueExpression(assignment.Value, $"evaluatedValue{index}");
|
||||
AssignVariable(assignment.Variable, $"evaluatedValue{index}");
|
||||
}
|
||||
#>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class SetMultipleVariablesTemplate
|
||||
{
|
||||
public SetMultipleVariablesTemplate(SetMultipleVariables model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
}
|
||||
|
||||
public SetMultipleVariables Model { get; }
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
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", "18.0.0.0")]
|
||||
internal partial class SetTextVariableTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </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/// <summary>\n/// Assigns an evaluated message template to the \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Variable));
|
||||
this.Write("\" variable.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n protected override async ValueTask<object?> ExecuteAsync(IWorkf" +
|
||||
"lowContext context, CancellationToken cancellationToken)\n {");
|
||||
|
||||
EvaluateMessageTemplate(this.Model.Value, "textValue");
|
||||
AssignVariable(this.Variable, "textValue");
|
||||
this.Write("\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 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));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateMessageTemplate(this.Model.Value, "textValue");
|
||||
AssignVariable(this.Variable, "textValue"); #>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class SetTextVariableTemplate
|
||||
{
|
||||
public SetTextVariableTemplate(SetTextVariable model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Variable = Throw.IfNull(this.Model.Variable);
|
||||
}
|
||||
|
||||
public SetTextVariable Model { get; }
|
||||
|
||||
public PropertyPath Variable { get; }
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 18.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
{
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "18.0.0.0")]
|
||||
internal partial class SetVariableTemplate : ActionTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public override string TransformText()
|
||||
{
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n");
|
||||
this.Write("\n/// <summary>\n/// Assigns an evaluated expression, other variable, or literal va" +
|
||||
"lue to the \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Model.Variable));
|
||||
this.Write("\" variable.\n/// </summary>\ninternal sealed class ");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Name));
|
||||
this.Write("Executor(FormulaSession session) : ActionExecutor(id: \"");
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(this.Id));
|
||||
this.Write("\", session)\n{\n // <inheritdoc />\n protected override async ValueTask<object" +
|
||||
"?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
|
||||
EvaluateValueExpression(this.Model.Value, "evaluatedValue");
|
||||
AssignVariable(this.Variable, "evaluatedValue");
|
||||
this.Write("\n return default;\n }\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 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);");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<#@ template language="C#" inherits="ActionTemplate" visibility="internal" linePragmas="false" #>
|
||||
<#@ output extension=".cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ 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>
|
||||
internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionExecutor(id: "<#= this.Id #>", session)
|
||||
{
|
||||
// <inheritdoc />
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
EvaluateValueExpression(this.Model.Value, "evaluatedValue");
|
||||
AssignVariable(this.Variable, "evaluatedValue"); #>
|
||||
return default;
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.ObjectModel;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
internal partial class SetVariableTemplate
|
||||
{
|
||||
internal SetVariableTemplate(SetVariable model)
|
||||
{
|
||||
this.Model = this.Initialize(model);
|
||||
this.Variable = Throw.IfNull(this.Model.Variable);
|
||||
}
|
||||
|
||||
public SetVariable Model { get; }
|
||||
public PropertyPath Variable { get; }
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
<#+
|
||||
void AssignVariable(PropertyPath targetVariable, string valueVariable, bool tightFormat = false)
|
||||
{
|
||||
if (targetVariable is not null)
|
||||
{#>
|
||||
await context.QueueStateUpdateAsync(key: "<#= VariableName(targetVariable) #>", value: <#= valueVariable #>, scopeName: "<#= VariableScope(targetVariable) #>").ConfigureAwait(false);<#+
|
||||
if (!tightFormat)
|
||||
{#>
|
||||
<#+}
|
||||
}
|
||||
}
|
||||
#>
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
<#+
|
||||
void EvaluateBoolExpression(BoolExpression expression, string targetVariable, bool defaultValue = false)
|
||||
{
|
||||
if (expression is null)
|
||||
{#>
|
||||
bool <#= targetVariable #> = <#= FormatBoolValue(defaultValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{#>
|
||||
bool <#= targetVariable #> = <#= FormatBoolValue(expression.LiteralValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
bool <#= targetVariable #> = await context.ReadStateAsync<bool>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
bool <#= targetVariable #> = await context.EvaluateValueAsync<bool>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
bool <#= targetVariable #> = await context.EvaluateValueAsync<bool>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
<#+
|
||||
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)
|
||||
{#>
|
||||
<#= resultType #> <#= targetVariable #> = <#= FormatValue<TValue>(defaultValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{
|
||||
resultMap.TryGetValue(expression.LiteralValue, out string resultValue);
|
||||
if (qualifyResult)
|
||||
{#>
|
||||
<#= resultType #> <#= targetVariable #> = <#= GetTypeAlias<TValue>() #>.<#= resultValue #>;<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= resultType #> <#= targetVariable #> = <#= FormatValue<TValue>(resultValue) #>;<#+
|
||||
}
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
<#= resultType #> <#= targetVariable #> = await context.ReadStateAsync<<#= resultType #>>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
<#= resultType #>? <#= targetVariable #> = await context.EvaluateValueAsync<<#= resultType #>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= resultType #> <#= targetVariable #> = await context.EvaluateValueAsync<<#= resultType #>>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
<#+
|
||||
void EvaluateIntExpression(IntExpression expression, string targetVariable, bool isNullable = false)
|
||||
{
|
||||
string typeName = isNullable ? "int?" : "int";
|
||||
if (expression is null)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = <#= isNullable ? "null" : "0" #>;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = <#= expression.LiteralValue #>;<#+
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = await context.ReadStateAsync<int>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
<#= typeName #>? <#= targetVariable #> = await context.EvaluateValueAsync<<#= typeName #>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = await context.EvaluateValueAsync<<#= typeName #>>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
<#+
|
||||
void EvaluateListExpression<TElement>(ValueExpression expression, string targetVariable)
|
||||
{
|
||||
string typeName = GetTypeAlias<TElement>();
|
||||
if (expression is null)
|
||||
{#>
|
||||
IList<<#= typeName #>>? <#= targetVariable #> = null;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{#>
|
||||
IList<<#= typeName #>>? <#= targetVariable #> = <#= FormatDataValue(expression.LiteralValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
IList<<#= typeName #>>? <#= targetVariable #> = await context.ReadListAsync<<#= GetTypeAlias<TElement>() #>>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
IList<<#= typeName #>>? <#= targetVariable #>> = await context.EvaluateListAsync<<#= typeName #>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
IList<<#= typeName #>>? <#= targetVariable #> = await context.EvaluateListAsync<<#= typeName #>>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
<#+
|
||||
void EvaluateRecordExpression<TValue>(ObjectExpression<RecordDataValue> expression, string targetVariable)
|
||||
{
|
||||
string resultTypeName = $"Dictionary<string, {GetTypeAlias<TValue>()}?>?";
|
||||
if (expression is null)
|
||||
{#>
|
||||
<#= resultTypeName #> <#= targetVariable #> = null;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{#>
|
||||
<#= resultTypeName #> <#= targetVariable #> =
|
||||
<#= FormatDataValue(expression.LiteralValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
<#= resultTypeName #> <#= targetVariable #> = await context.ReadStateAsync<<#= resultTypeName #>>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
<#= resultTypeName #>? <#= targetVariable #> = await context.EvaluateExpressionAsync<<#= resultTypeName #>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= resultTypeName #> <#= targetVariable #> = await context.EvaluateExpressionAsync<<#= resultTypeName #>>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
<#+
|
||||
void EvaluateStringExpression(StringExpression expression, string targetVariable, bool isNullable = false)
|
||||
{
|
||||
string typeName = isNullable ? "string?" : "string";
|
||||
if (expression is null)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = <#= isNullable ? "null" : "string.Empty" #>;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{
|
||||
if (expression.LiteralValue.Contains("\n"))
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> =
|
||||
"""
|
||||
<#= expression.LiteralValue #>
|
||||
""";<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = <#= FormatStringValue(expression.LiteralValue) #>;<#+
|
||||
}
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = await context.ReadStateAsync<string>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = await context.EvaluateValueAsync<string>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= typeName #> <#= targetVariable #> = await context.EvaluateValueAsync<string>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
<#+
|
||||
void EvaluateValueExpression(ValueExpression expression, string targetVariable) =>
|
||||
EvaluateValueExpression<object>(expression, targetVariable);
|
||||
|
||||
void EvaluateValueExpression<TValue>(ValueExpression expression, string targetVariable)
|
||||
{
|
||||
if (expression is null)
|
||||
{#>
|
||||
<#= GetTypeAlias<TValue>() #>? <#= targetVariable #> = null;<#+
|
||||
}
|
||||
else if (expression.IsLiteral)
|
||||
{#>
|
||||
<#= GetTypeAlias<TValue>() #>? <#= targetVariable #> = <#= FormatDataValue(expression.LiteralValue) #>;<#+
|
||||
}
|
||||
else if (expression.IsVariableReference && expression.VariableReference.SegmentCount == 2)
|
||||
{#>
|
||||
<#= GetTypeAlias<TValue>() #>? <#= targetVariable #> = await context.ReadStateAsync<<#= GetTypeAlias<TValue>() #>>(key: "<#= expression.VariableReference.VariableName #>", scopeName: "<#= expression.VariableReference.NamespaceAlias #>").ConfigureAwait(false);<#+
|
||||
}
|
||||
else if (expression.IsVariableReference)
|
||||
{#>
|
||||
<#= GetTypeAlias<TValue>() #>? <#= targetVariable #> = await context.EvaluateValueAsync<<#= GetTypeAlias<TValue>() #>>(<#= FormatStringValue(expression.VariableReference.ToString()) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
<#= GetTypeAlias<TValue>() #>? <#= targetVariable #> = await context.EvaluateValueAsync<<#= GetTypeAlias<TValue>() #>>(<#= FormatStringValue(expression.ExpressionText) #>).ConfigureAwait(false);<#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
<#+
|
||||
void EvaluateMessageTemplate(TemplateLine templateLine, string variableName)
|
||||
{
|
||||
if (templateLine is not null)
|
||||
{#>
|
||||
string <#= variableName #> =
|
||||
await context.FormatTemplateAsync(
|
||||
"""<#+
|
||||
FormatMessageTemplate(templateLine); #>
|
||||
""");<#+
|
||||
}
|
||||
else
|
||||
{#>
|
||||
string? <#= variableName #> = null;<#+
|
||||
}
|
||||
}
|
||||
|
||||
void FormatMessageTemplate(TemplateLine line)
|
||||
{
|
||||
foreach (string text in line.ToTemplateString().ByLine())
|
||||
{ #>
|
||||
<#= text #><#+
|
||||
}
|
||||
}
|
||||
#>
|
||||
@@ -87,55 +87,6 @@ public static class DeclarativeWorkflowBuilder
|
||||
return visitor.Complete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates source code (provider/executor scaffolding) for the workflow defined in the YAML file.
|
||||
/// </summary>
|
||||
/// <param name="workflowFile">The path to the workflow YAML file.</param>
|
||||
/// <param name="workflowLanguage">The language to use for the generated code.</param>
|
||||
/// <param name="workflowNamespace">Optional target namespace for the generated code.</param>
|
||||
/// <param name="workflowPrefix">Optional prefix for generated workflow type.</param>
|
||||
/// <returns>The generated source code representing the workflow.</returns>
|
||||
public static string Eject(
|
||||
string workflowFile,
|
||||
DeclarativeWorkflowLanguage workflowLanguage,
|
||||
string? workflowNamespace = null,
|
||||
string? workflowPrefix = null)
|
||||
{
|
||||
using StreamReader yamlReader = File.OpenText(workflowFile);
|
||||
return Eject(yamlReader, workflowLanguage, workflowNamespace, workflowPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates source code (provider/executor scaffolding) for the workflow defined in the provided YAML reader.
|
||||
/// </summary>
|
||||
/// <param name="yamlReader">The reader supplying the workflow YAML.</param>
|
||||
/// <param name="workflowLanguage">The language to use for the generated code.</param>
|
||||
/// <param name="workflowNamespace">Optional target namespace for the generated code.</param>
|
||||
/// <param name="workflowPrefix">Optional prefix for generated workflow type.</param>
|
||||
/// <returns>The generated source code representing the workflow.</returns>
|
||||
public static string Eject(
|
||||
TextReader yamlReader,
|
||||
DeclarativeWorkflowLanguage workflowLanguage,
|
||||
string? workflowNamespace = null,
|
||||
string? workflowPrefix = null)
|
||||
{
|
||||
if (workflowLanguage != DeclarativeWorkflowLanguage.CSharp)
|
||||
{
|
||||
throw new NotSupportedException($"Converting workflow to {workflowLanguage} is not currently supported.");
|
||||
}
|
||||
|
||||
AdaptiveDialog workflowElement = ReadWorkflow(yamlReader);
|
||||
|
||||
string rootId = WorkflowActionVisitor.Steps.Root(workflowElement);
|
||||
WorkflowTypeInfo typeInfo = workflowElement.WrapWithBot().Describe();
|
||||
|
||||
WorkflowTemplateVisitor visitor = new(rootId, typeInfo);
|
||||
WorkflowElementWalker walker = new(visitor);
|
||||
walker.Visit(workflowElement);
|
||||
|
||||
return visitor.Complete(workflowNamespace, workflowPrefix);
|
||||
}
|
||||
|
||||
private static AdaptiveDialog ReadWorkflow(TextReader yamlReader)
|
||||
{
|
||||
BotElement rootElement = YamlSerializer.Deserialize<BotElement>(yamlReader) ?? throw new DeclarativeModelException("Workflow undefined.");
|
||||
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Agents.AI.Workflows.Declarative.CodeGen;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
|
||||
|
||||
internal sealed class WorkflowCodeBuilder : IModelBuilder<string>
|
||||
{
|
||||
private readonly HashSet<string> _actions;
|
||||
private readonly List<string> _definitions;
|
||||
private readonly List<string> _instances;
|
||||
private readonly List<string> _edges;
|
||||
private readonly string _rootId;
|
||||
|
||||
public WorkflowCodeBuilder(string rootId)
|
||||
{
|
||||
this._actions = [];
|
||||
this._definitions = [];
|
||||
this._instances = [];
|
||||
this._edges = [];
|
||||
this._rootId = rootId;
|
||||
}
|
||||
|
||||
public string GenerateCode(string? workflowNamespace, string? workflowPrefix)
|
||||
{
|
||||
ProviderTemplate template =
|
||||
new(this._rootId, this._definitions, this._instances, this._edges)
|
||||
{
|
||||
Namespace = workflowNamespace,
|
||||
Prefix = workflowPrefix,
|
||||
};
|
||||
|
||||
return template.TransformText().Trim();
|
||||
}
|
||||
|
||||
public void Connect(IModeledAction source, IModeledAction target, string? condition)
|
||||
{
|
||||
Debug.WriteLine($"> CONNECT: {source.Id} => {target.Id}{(condition is null ? string.Empty : " (?)")}");
|
||||
|
||||
this.HandelAction(source);
|
||||
this.HandelAction(target);
|
||||
|
||||
this._edges.Add(new EdgeTemplate(source.Id, target.Id, condition).TransformText());
|
||||
}
|
||||
|
||||
private void HandelAction(IModeledAction action)
|
||||
{
|
||||
// All templates are based on "CodeTemplate"
|
||||
if (action is not CodeTemplate template)
|
||||
{
|
||||
// Something has gone very wrong.
|
||||
throw new DeclarativeModelException($"Unable to generate code for: {action.GetType().Name}.");
|
||||
}
|
||||
|
||||
if (this._actions.Add(action.Id))
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EmptyTemplate:
|
||||
case DefaultTemplate:
|
||||
this._instances.Add(template.TransformText());
|
||||
break;
|
||||
case ActionTemplate actionTemplate:
|
||||
this._definitions.Add(template.TransformText());
|
||||
this._instances.Add(new InstanceTemplate(action.Id, this._rootId, actionTemplate.UseAgentProvider).TransformText());
|
||||
break;
|
||||
case RootTemplate:
|
||||
this._definitions.Add(template.TransformText());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user