Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,15 +196,15 @@ private static void CoalesceImageResultContent(IList<AIContent> contents)

for (int i = 0; i < contents.Count; i++)
{
if (contents[i] is ImageGenerationToolResultContent imageResult && !string.IsNullOrEmpty(imageResult.ImageId))
if (contents[i] is ImageGenerationToolResultContent imageResult)
{
// Check if there's an existing ImageGenerationToolResultContent with the same ImageId to replace
// Check if there's an existing ImageGenerationToolResultContent with the same CallId to replace
if (imageResultIndexById is null)
{
imageResultIndexById = new(StringComparer.Ordinal);
}

if (imageResultIndexById.TryGetValue(imageResult.ImageId!, out int existingIndex))
if (imageResultIndexById.TryGetValue(imageResult.CallId, out int existingIndex))
{
// Replace the existing imageResult with the new one
contents[existingIndex] = imageResult;
Expand All @@ -213,7 +213,7 @@ private static void CoalesceImageResultContent(IList<AIContent> contents)
}
else
{
imageResultIndexById[imageResult.ImageId!] = i;
imageResultIndexById[imageResult.CallId] = i;
}
}
}
Expand Down Expand Up @@ -320,9 +320,8 @@ internal static void CoalesceContent(IList<AIContent> contents)
CoalesceContent(inputs);
}

return new()
return new(firstContent.CallId)
{
CallId = firstContent.CallId,
Inputs = inputs,
AdditionalProperties = firstContent.AdditionalProperties?.Clone(),
};
Expand All @@ -331,7 +330,7 @@ internal static void CoalesceContent(IList<AIContent> contents)
Coalesce<CodeInterpreterToolResultContent>(
contents,
mergeSingle: true,
canMerge: static (r1, r2) => r1.CallId is not null && r2.CallId is not null && r1.CallId == r2.CallId,
canMerge: static (r1, r2) => r1.CallId == r2.CallId,
static (contents, start, end) =>
{
var firstContent = (CodeInterpreterToolResultContent)contents[start];
Expand All @@ -358,9 +357,8 @@ internal static void CoalesceContent(IList<AIContent> contents)
CoalesceContent(output);
}

return new()
return new(firstContent.CallId)
{
CallId = firstContent.CallId,
Outputs = output,
AdditionalProperties = firstContent.AdditionalProperties?.Clone(),
};
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ namespace Microsoft.Extensions.AI;
[JsonDerivedType(typeof(TextReasoningContent), typeDiscriminator: "reasoning")]
[JsonDerivedType(typeof(UriContent), typeDiscriminator: "uri")]
[JsonDerivedType(typeof(UsageContent), typeDiscriminator: "usage")]
[JsonDerivedType(typeof(ToolApprovalRequestContent), typeDiscriminator: "toolApprovalRequest")]
[JsonDerivedType(typeof(ToolApprovalResponseContent), typeDiscriminator: "toolApprovalResponse")]
[JsonDerivedType(typeof(McpServerToolCallContent), typeDiscriminator: "mcpServerToolCall")]
[JsonDerivedType(typeof(McpServerToolResultContent), typeDiscriminator: "mcpServerToolResult")]

// These should be added in once they're no longer [Experimental]. If they're included while still
// experimental, any JsonSerializerContext that includes AIContent will incur errors about using
// experimental types in its source generated files. When [Experimental] is removed from these types,
// these lines should be uncommented and the corresponding lines in AIJsonUtilities.CreateDefaultOptions
// as well as the [JsonSerializable] attributes for them on the JsonContext should be removed.
// [JsonDerivedType(typeof(FunctionApprovalRequestContent), typeDiscriminator: "functionApprovalRequest")]
// [JsonDerivedType(typeof(FunctionApprovalResponseContent), typeDiscriminator: "functionApprovalResponse")]
// [JsonDerivedType(typeof(McpServerToolCallContent), typeDiscriminator: "mcpServerToolCall")]
// [JsonDerivedType(typeof(McpServerToolResultContent), typeDiscriminator: "mcpServerToolResult")]
// [JsonDerivedType(typeof(McpServerToolApprovalRequestContent), typeDiscriminator: "mcpServerToolApprovalRequest")]
// [JsonDerivedType(typeof(McpServerToolApprovalResponseContent), typeDiscriminator: "mcpServerToolApprovalResponse")]
// [JsonDerivedType(typeof(CodeInterpreterToolCallContent), typeDiscriminator: "codeInterpreterToolCall")]
// [JsonDerivedType(typeof(CodeInterpreterToolResultContent), typeDiscriminator: "codeInterpreterToolResult")]
// [JsonDerivedType(typeof(ImageGenerationToolCallContent), typeDiscriminator: "imageGenerationToolCall")]
// [JsonDerivedType(typeof(ImageGenerationToolResultContent), typeDiscriminator: "imageGenerationToolResult")]

public class AIContent
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,17 @@ namespace Microsoft.Extensions.AI;
/// It is informational only and represents the call itself, not the result.
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AICodeInterpreter, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class CodeInterpreterToolCallContent : AIContent
public sealed class CodeInterpreterToolCallContent : ToolCallContent
{
/// <summary>
/// Initializes a new instance of the <see cref="CodeInterpreterToolCallContent"/> class.
/// </summary>
public CodeInterpreterToolCallContent()
/// <param name="callId">The tool call ID.</param>
public CodeInterpreterToolCallContent(string callId)
: base(callId)
{
}

/// <summary>
/// Gets or sets the tool call ID.
/// </summary>
public string? CallId { get; set; }

/// <summary>
/// Gets or sets the inputs to the code interpreter tool.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,17 @@ namespace Microsoft.Extensions.AI;
/// Represents the result of a code interpreter tool invocation by a hosted service.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AICodeInterpreter, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class CodeInterpreterToolResultContent : AIContent
public sealed class CodeInterpreterToolResultContent : ToolResultContent
{
/// <summary>
/// Initializes a new instance of the <see cref="CodeInterpreterToolResultContent"/> class.
/// </summary>
public CodeInterpreterToolResultContent()
/// <param name="callId">The tool call ID.</param>
public CodeInterpreterToolResultContent(string callId)
: base(callId)
{
}

/// <summary>
/// Gets or sets the tool call ID that this result corresponds to.
/// </summary>
public string? CallId { get; set; }

/// <summary>
/// Gets or sets the output of code interpreter tool.
/// </summary>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.Extensions.AI;
/// Represents a function call request.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class FunctionCallContent : AIContent
public class FunctionCallContent : ToolCallContent
{
/// <summary>
/// Initializes a new instance of the <see cref="FunctionCallContent"/> class.
Expand All @@ -24,17 +24,12 @@ public class FunctionCallContent : AIContent
/// <param name="arguments">The function original arguments.</param>
[JsonConstructor]
public FunctionCallContent(string callId, string name, IDictionary<string, object?>? arguments = null)
: base(callId)
{
CallId = Throw.IfNull(callId);
Name = Throw.IfNull(name);
Arguments = arguments;
}

/// <summary>
/// Gets the function call ID.
/// </summary>
public string CallId { get; }

/// <summary>
/// Gets the name of the function requested.
/// </summary>
Expand All @@ -51,7 +46,7 @@ public FunctionCallContent(string callId, string name, IDictionary<string, objec
/// <remarks>
/// This property is for information purposes only. The <see cref="Exception"/> is not serialized as part of serializing
/// instances of this class with <see cref="JsonSerializer"/>; as such, upon deserialization, this property will be <see langword="null"/>.
/// Consumers should not rely on <see langword="null"/> indicating success.
/// Consumers should not rely on <see langword="null"/> indicating success.
/// </remarks>
[JsonIgnore]
public Exception? Exception { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Shared.Diagnostics;

namespace Microsoft.Extensions.AI;

/// <summary>
/// Represents the result of a function call.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class FunctionResultContent : AIContent
public class FunctionResultContent : ToolResultContent
{
/// <summary>
/// Initializes a new instance of the <see cref="FunctionResultContent"/> class.
Expand All @@ -26,20 +25,11 @@ public class FunctionResultContent : AIContent
/// </param>
[JsonConstructor]
public FunctionResultContent(string callId, object? result)
: base(callId)
{
CallId = Throw.IfNull(callId);
Result = result;
}

/// <summary>
/// Gets the ID of the function call for which this is the result.
/// </summary>
/// <remarks>
/// If this is the result for a <see cref="FunctionCallContent"/>, this property should contain the same
/// <see cref="FunctionCallContent.CallId"/> value.
/// </remarks>
public string CallId { get; }

/// <summary>
/// Gets or sets the result of the function call, or a generic error message if the function call failed.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@ namespace Microsoft.Extensions.AI;
/// Represents the invocation of an image generation tool call by a hosted service.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AIImageGeneration, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class ImageGenerationToolCallContent : AIContent
public sealed class ImageGenerationToolCallContent : ToolCallContent
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageGenerationToolCallContent"/> class.
/// </summary>
public ImageGenerationToolCallContent()
/// <param name="callId">The tool call ID.</param>
public ImageGenerationToolCallContent(string callId)
: base(callId)
{
}

/// <summary>
/// Gets or sets the unique identifier of the image generation item.
/// </summary>
public string? ImageId { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,17 @@ namespace Microsoft.Extensions.AI;
/// It is informational only and represents the call itself, not the result.
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AIImageGeneration, UrlFormat = DiagnosticIds.UrlFormat)]
public sealed class ImageGenerationToolResultContent : AIContent
public sealed class ImageGenerationToolResultContent : ToolResultContent
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageGenerationToolResultContent"/> class.
/// </summary>
public ImageGenerationToolResultContent()
/// <param name="callId">The tool call ID.</param>
public ImageGenerationToolResultContent(string callId)
: base(callId)
{
}

/// <summary>
/// Gets or sets the unique identifier of the image generation item.
/// </summary>
public string? ImageId { get; set; }

/// <summary>
/// Gets or sets the generated content items.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Text.Json.Serialization;
using Microsoft.Shared.Diagnostics;

namespace Microsoft.Extensions.AI;

/// <summary>
/// Represents a request for input from the user or application.
/// </summary>
[JsonDerivedType(typeof(ToolApprovalRequestContent), "toolApprovalRequest")]
public class InputRequestContent : AIContent
{
/// <summary>
/// Initializes a new instance of the <see cref="InputRequestContent"/> class.
/// </summary>
/// <param name="requestId">The unique identifier that correlates this request with its corresponding response.</param>
/// <exception cref="ArgumentNullException"><paramref name="requestId"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="requestId"/> is empty or composed entirely of whitespace.</exception>
protected InputRequestContent(string requestId)
{
RequestId = Throw.IfNullOrWhitespace(requestId);
}

/// <summary>
/// Gets the unique identifier that correlates this request with its corresponding <see cref="InputResponseContent"/>.
/// </summary>
public string RequestId { get; }
}
Loading
Loading