diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Converters/ItemResourceExtensions.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Converters/ItemResourceExtensions.cs
deleted file mode 100644
index c9e92dda60..0000000000
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Converters/ItemResourceExtensions.cs
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json;
-using Microsoft.Agents.AI.Hosting.OpenAI.Responses.Models;
-using Microsoft.Extensions.AI;
-
-namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses.Converters;
-
-///
-/// Extension methods for converting between ItemResource and ChatMessage.
-///
-internal static class ItemResourceExtensions
-{
- ///
- /// Converts an ItemResource to a ChatMessage.
- ///
- /// The ItemResource to convert.
- /// A ChatMessage.
- /// Thrown when the ItemResource type is not supported for conversion to ChatMessage.
- public static ChatMessage ToChatMessage(this ItemResource itemResource)
- {
- if (itemResource is ResponsesMessageItemResource messageItem)
- {
- var content = messageItem switch
- {
- ResponsesAssistantMessageItemResource assistant => assistant.Content,
- ResponsesUserMessageItemResource user => user.Content,
- ResponsesSystemMessageItemResource system => system.Content,
- ResponsesDeveloperMessageItemResource developer => developer.Content,
- _ => throw new NotSupportedException($"Message item type {messageItem.GetType().Name} not supported")
- };
-
- // Convert ItemContent to AIContent using the existing converter
- var aiContents = content
- .Select(ItemContentConverter.ToAIContent)
- .Where(c => c is not null)
- .ToList();
- return new ChatMessage(messageItem.Role, aiContents!);
- }
-
- if (itemResource is FunctionToolCallItemResource functionCall)
- {
- return new ChatMessage(ChatRole.Assistant, [
- functionCall.ToFunctionCallContent()
- ]);
- }
-
- if (itemResource is FunctionToolCallOutputItemResource functionOutput)
- {
- return new ChatMessage(ChatRole.Tool, [
- functionOutput.ToFunctionResultContent()
- ]);
- }
-
- throw new NotSupportedException($"ItemResource type {itemResource.GetType().Name} not supported for conversion to ChatMessage");
- }
-
- ///
- /// Converts a ChatMessage to ItemResource objects.
- /// This method requires an IdGenerator to create unique IDs for the generated resources.
- ///
- /// The chat message to convert.
- /// The ID generator to use for creating IDs.
- /// The JSON serializer options to use.
- /// An enumerable of ItemResource objects.
- public static IEnumerable ToItemResources(this ChatMessage message, IdGenerator idGenerator, JsonSerializerOptions jsonSerializerOptions)
- {
- return message.ToItemResource(idGenerator, jsonSerializerOptions);
- }
-
- ///
- /// Converts a ChatMessage to a single ItemResource (message type) when it contains only message content.
- /// For messages with function calls, use ToItemResources instead.
- ///
- /// The chat message to convert.
- /// The ID to assign to the message resource.
- /// A ResponsesMessageItemResource.
- /// Thrown when the message contains function calls or function results.
- public static ResponsesMessageItemResource ToMessageItemResource(this ChatMessage message, string id)
- {
- // Check if the message contains function calls or function results
- if (message.Contents.Any(c => c is FunctionCallContent or FunctionResultContent))
- {
- throw new InvalidOperationException("Cannot convert a ChatMessage with function calls or function results to a single MessageItemResource. Use ToItemResources instead.");
- }
-
- // Convert all contents to ItemContent
- var contents = message.Contents
- .Select(ItemContentConverter.ToItemContent)
- .Where(c => c is not null)
- .ToList();
-
- // Create the appropriate message item resource based on role
- return message.Role.Value switch
- {
- "assistant" => new ResponsesAssistantMessageItemResource
- {
- Id = id,
- Status = ResponsesMessageItemResourceStatus.Completed,
- Content = contents!
- },
- "user" => new ResponsesUserMessageItemResource
- {
- Id = id,
- Status = ResponsesMessageItemResourceStatus.Completed,
- Content = contents!
- },
- "system" => new ResponsesSystemMessageItemResource
- {
- Id = id,
- Status = ResponsesMessageItemResourceStatus.Completed,
- Content = contents!
- },
- "developer" => new ResponsesDeveloperMessageItemResource
- {
- Id = id,
- Status = ResponsesMessageItemResourceStatus.Completed,
- Content = contents!
- },
- _ => new ResponsesAssistantMessageItemResource
- {
- Id = id,
- Status = ResponsesMessageItemResourceStatus.Completed,
- Content = contents!
- }
- };
- }
-
- ///
- /// Converts multiple ItemResources to ChatMessages.
- /// Adjacent message items with the same role will be combined into a single ChatMessage.
- ///
- /// The ItemResources to convert.
- /// An enumerable of ChatMessages.
- public static IEnumerable ToChatMessages(this IEnumerable itemResources)
- {
- ChatMessage? currentMessage = null;
- var currentContents = new List();
-
- foreach (var item in itemResources)
- {
- if (item is ResponsesMessageItemResource messageItem)
- {
- // Check if we should start a new message or continue the current one
- if (currentMessage is not null && currentMessage.Role != messageItem.Role)
- {
- // Yield the current message and start a new one
- yield return new ChatMessage(currentMessage.Role, [.. currentContents]);
- currentContents = [];
- }
-
- // Add contents from this message item
- var aiContents = messageItem switch
- {
- ResponsesAssistantMessageItemResource assistant => assistant.Content,
- ResponsesUserMessageItemResource user => user.Content,
- ResponsesSystemMessageItemResource system => system.Content,
- ResponsesDeveloperMessageItemResource developer => developer.Content,
- _ => []
- };
-
- foreach (var content in aiContents)
- {
- if (ItemContentConverter.ToAIContent(content) is { } aiContent)
- {
- currentContents.Add(aiContent);
- }
- }
-
- // Initialize or update current message
- currentMessage = new ChatMessage(messageItem.Role, [.. currentContents]);
- }
- else if (item is FunctionToolCallItemResource functionCall)
- {
- // Function calls are always from assistant
- if (currentMessage is not null && currentMessage.Role != ChatRole.Assistant)
- {
- yield return new ChatMessage(currentMessage.Role, [.. currentContents]);
- currentContents = [];
- currentMessage = null;
- }
-
- currentContents.Add(functionCall.ToFunctionCallContent());
- currentMessage = new ChatMessage(ChatRole.Assistant, [.. currentContents]);
- }
- else if (item is FunctionToolCallOutputItemResource functionOutput)
- {
- // Function outputs are always from tool role
- if (currentMessage is not null && currentMessage.Role != ChatRole.Tool)
- {
- yield return new ChatMessage(currentMessage.Role, [.. currentContents]);
- currentContents = [];
- currentMessage = null;
- }
-
- currentContents.Add(functionOutput.ToFunctionResultContent());
- currentMessage = new ChatMessage(ChatRole.Tool, [.. currentContents]);
- }
- }
-
- // Yield the last message if any
- if (currentMessage is not null && currentContents.Count > 0)
- {
- yield return new ChatMessage(currentMessage.Role, [.. currentContents]);
- }
- }
-
- ///
- /// Converts a FunctionToolCallItemResource to FunctionCallContent.
- /// Uses the official Microsoft.Extensions.AI pattern via CreateFromParsedArguments to properly handle parsing errors.
- ///
- /// The function call item resource to convert.
- /// A FunctionCallContent with properly parsed arguments. If parsing fails, the Exception property will be set.
- public static FunctionCallContent ToFunctionCallContent(this FunctionToolCallItemResource functionCall)
- {
- // Use the same pattern as Microsoft.Extensions.AI.OpenAI's ParseCallContent method
- // This properly handles parsing errors by setting the Exception property on FunctionCallContent
- return FunctionCallContent.CreateFromParsedArguments(
- functionCall.Arguments ?? "{}",
- functionCall.CallId,
- functionCall.Name,
- static json => (IDictionary)JsonSerializer.Deserialize(json, OpenAIHostingJsonUtilities.DefaultOptions.GetTypeInfo(typeof(IDictionary)))!);
- }
-
- ///
- /// Converts a FunctionToolCallOutputItemResource to FunctionResultContent.
- ///
- /// The function output item resource to convert.
- /// A FunctionResultContent.
- public static FunctionResultContent ToFunctionResultContent(this FunctionToolCallOutputItemResource functionOutput)
- {
- return new FunctionResultContent(functionOutput.CallId, functionOutput.Output);
- }
-
- ///
- /// Converts a ChatMessage to ItemParam objects (input models without IDs).
- /// This is useful for creating items in the Conversations API.
- /// Filters out events that don't map well to ItemParams (e.g., messages with no convertible content).
- ///
- /// The chat message to convert.
- /// An enumerable of ItemParam objects.
- public static IEnumerable ToItemParams(this ChatMessage message)
- {
- // Separate function call/result contents from regular message contents
- foreach (AIContent content in message.Contents)
- {
- switch (content)
- {
- case FunctionCallContent functionCallContent:
- yield return new FunctionToolCallItemParam
- {
- CallId = functionCallContent.CallId,
- Name = functionCallContent.Name,
- Arguments = JsonSerializer.Serialize(
- functionCallContent.Arguments,
- OpenAIHostingJsonUtilities.DefaultOptions.GetTypeInfo(typeof(IDictionary)))
- };
- break;
-
- case FunctionResultContent functionResultContent:
- string output = functionResultContent.Exception is not null
- ? $"{functionResultContent.Exception.GetType().Name}(\"{functionResultContent.Exception.Message}\")"
- : $"{functionResultContent.Result?.ToString() ?? "(null)"}";
- yield return new FunctionToolCallOutputItemParam
- {
- CallId = functionResultContent.CallId,
- Output = output
- };
- break;
- }
- }
-
- // Convert regular message contents
- List regularContents = [];
- foreach (AIContent content in message.Contents)
- {
- if (content is not FunctionCallContent and not FunctionResultContent &&
- ItemContentConverter.ToItemContent(content) is { } itemContent)
- {
- regularContents.Add(itemContent);
- }
- }
-
- // Only create a message item if we have convertible contents
- // This filters out messages that contain only non-convertible content (e.g., UsageContent)
- if (regularContents.Count > 0)
- {
- InputMessageContent messageContent = InputMessageContent.FromContents(regularContents);
-
- yield return message.Role.Value.ToUpperInvariant() switch
- {
- "USER" => new ResponsesUserMessageItemParam { Content = messageContent },
- "ASSISTANT" => new ResponsesAssistantMessageItemParam { Content = messageContent },
- "SYSTEM" => new ResponsesSystemMessageItemParam { Content = messageContent },
- "DEVELOPER" => new ResponsesDeveloperMessageItemParam { Content = messageContent },
- _ => new ResponsesUserMessageItemParam { Content = messageContent }
- };
- }
- }
-
- ///
- /// Converts a ChatMessage to a single ItemParam (message type) when it contains only message content.
- /// For messages with function calls, use ToItemParams instead.
- ///
- /// The chat message to convert.
- /// A ResponsesMessageItemParam.
- /// Thrown when the message contains function calls or function results.
- public static ResponsesMessageItemParam ToMessageItemParam(this ChatMessage message)
- {
- // Check if the message contains function calls or function results
- if (message.Contents.Any(c => c is FunctionCallContent or FunctionResultContent))
- {
- throw new InvalidOperationException("Cannot convert a ChatMessage with function calls or function results to a single MessageItemParam. Use ToItemParams instead.");
- }
-
- // Convert all contents to ItemContent
- List contents = [];
- foreach (AIContent content in message.Contents)
- {
- if (ItemContentConverter.ToItemContent(content) is { } itemContent)
- {
- contents.Add(itemContent);
- }
- }
-
- // Create InputMessageContent
- InputMessageContent messageContent = contents.Count > 0
- ? InputMessageContent.FromContents(contents)
- : InputMessageContent.FromText(message.Text ?? string.Empty);
-
- // Create the appropriate message item param based on role
- return message.Role.Value.ToUpperInvariant() switch
- {
- "USER" => new ResponsesUserMessageItemParam { Content = messageContent },
- "ASSISTANT" => new ResponsesAssistantMessageItemParam { Content = messageContent },
- "SYSTEM" => new ResponsesSystemMessageItemParam { Content = messageContent },
- "DEVELOPER" => new ResponsesDeveloperMessageItemParam { Content = messageContent },
- _ => new ResponsesUserMessageItemParam { Content = messageContent }
- };
- }
-}