mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
a3a9147e61
* Rename AgentThread to AgentSession * Add more renames * Update readme files * Revert nullable variable change and further fixes. * Revert change in header name * Fix some comments and tests * Update changelog. * Address PR feedback. * Fixing code review comments. * Fix new errors after merging latest code.
100 lines
4.9 KiB
C#
100 lines
4.9 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Text.Encodings.Web;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using Microsoft.Agents.AI.DurableTask.State;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
namespace Microsoft.Agents.AI.DurableTask;
|
|
|
|
/// <summary>Provides JSON serialization utilities and source-generated contracts for Durable Agent types.</summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This mirrors the pattern used by other libraries (e.g. <c>WorkflowsJsonUtilities</c>) to enable Native AOT and trimming
|
|
/// friendly serialization without relying on runtime reflection. It establishes a singleton <see cref="JsonSerializerOptions"/>
|
|
/// instance that is preconfigured with:
|
|
/// </para>
|
|
/// <list type="number">
|
|
/// <item><description><see cref="JsonSerializerDefaults.Web"/> baseline defaults.</description></item>
|
|
/// <item><description><see cref="JsonIgnoreCondition.WhenWritingNull"/> for default null-value suppression.</description></item>
|
|
/// <item><description><see cref="JsonNumberHandling.AllowReadingFromString"/> to tolerate numbers encoded as strings.</description></item>
|
|
/// <item><description>Chained type info resolvers from shared agent abstractions to cover cross-package types (e.g. <see cref="ChatMessage"/>, <see cref="AgentResponse"/>).</description></item>
|
|
/// </list>
|
|
/// <para>
|
|
/// Keep the list of <c>[JsonSerializable]</c> types in sync with the Durable Agent data model anytime new state or request/response
|
|
/// containers are introduced that must round-trip via JSON.
|
|
/// </para>
|
|
/// </remarks>
|
|
internal static partial class DurableAgentJsonUtilities
|
|
{
|
|
/// <summary>
|
|
/// Gets the singleton <see cref="JsonSerializerOptions"/> used for Durable Agent serialization.
|
|
/// </summary>
|
|
public static JsonSerializerOptions DefaultOptions { get; } = CreateDefaultOptions();
|
|
|
|
/// <summary>
|
|
/// Serializes a sequence of chat messages using the durable agent default options.
|
|
/// </summary>
|
|
/// <param name="messages">The messages to serialize.</param>
|
|
/// <returns>A <see cref="JsonElement"/> representing the serialized messages.</returns>
|
|
public static JsonElement Serialize(this IEnumerable<ChatMessage> messages) =>
|
|
JsonSerializer.SerializeToElement(messages, DefaultOptions.GetTypeInfo(typeof(IEnumerable<ChatMessage>)));
|
|
|
|
/// <summary>
|
|
/// Deserializes chat messages from a <see cref="JsonElement"/> using durable agent options.
|
|
/// </summary>
|
|
/// <param name="element">The JSON element containing the messages.</param>
|
|
/// <returns>The deserialized list of chat messages.</returns>
|
|
public static List<ChatMessage> DeserializeMessages(this JsonElement element) =>
|
|
(List<ChatMessage>?)element.Deserialize(DefaultOptions.GetTypeInfo(typeof(List<ChatMessage>))) ?? [];
|
|
|
|
/// <summary>
|
|
/// Creates the configured <see cref="JsonSerializerOptions"/> instance for durable agents.
|
|
/// </summary>
|
|
/// <returns>The configured options.</returns>
|
|
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresDynamicCode", Justification = "Converter is guarded by IsReflectionEnabledByDefault check.")]
|
|
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access", Justification = "Converter is guarded by IsReflectionEnabledByDefault check.")]
|
|
private static JsonSerializerOptions CreateDefaultOptions()
|
|
{
|
|
// Base configuration from the source-generated context below.
|
|
JsonSerializerOptions options = new(JsonContext.Default.Options)
|
|
{
|
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // same as AgentAbstractionsJsonUtilities and AIJsonUtilities
|
|
};
|
|
|
|
// Chain in shared abstractions resolver (Microsoft.Extensions.AI + Agent abstractions) so dependent types are covered.
|
|
options.TypeInfoResolverChain.Clear();
|
|
options.TypeInfoResolverChain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver!);
|
|
options.TypeInfoResolverChain.Add(JsonContext.Default.Options.TypeInfoResolver!);
|
|
|
|
if (JsonSerializer.IsReflectionEnabledByDefault)
|
|
{
|
|
options.Converters.Add(new JsonStringEnumConverter());
|
|
}
|
|
|
|
options.MakeReadOnly();
|
|
return options;
|
|
}
|
|
|
|
// Keep in sync with CreateDefaultOptions above.
|
|
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web,
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
NumberHandling = JsonNumberHandling.AllowReadingFromString)]
|
|
|
|
// Durable Agent State Types
|
|
[JsonSerializable(typeof(DurableAgentState))]
|
|
[JsonSerializable(typeof(DurableAgentSession))]
|
|
|
|
// Request Types
|
|
[JsonSerializable(typeof(RunRequest))]
|
|
|
|
// Primitive / Supporting Types
|
|
[JsonSerializable(typeof(ChatMessage))]
|
|
[JsonSerializable(typeof(JsonElement))]
|
|
|
|
[ExcludeFromCodeCoverage]
|
|
internal sealed partial class JsonContext : JsonSerializerContext;
|
|
}
|