Skip to content
6 changes: 6 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<add key="dotnet9-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9-transport/nuget/v3/index.json" />
<!-- Used for the Rich Navigation indexing task -->
<add key="richnav" value="https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-buildservices/nuget/v3/index.json" />
<!-- Used for pre-release OpenAI SDK packages; can be removed once a stable release is published -->
<add key="github-openai" value="https://nuget.pkg.github.com/openai/index.json" />
</packageSources>
<!-- Define mappings by adding package patterns beneath the target source.
https://aka.ms/nuget-package-source-mapping -->
Expand All @@ -39,6 +41,10 @@
<packageSource key="richnav">
<package pattern="*" />
</packageSource>
<packageSource key="github-openai">
<package pattern="OpenAI" />
<package pattern="OpenAI.Responses" />
</packageSource>
</packageSourceMapping>
<disabledPackageSources>
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
Expand Down
2 changes: 1 addition & 1 deletion eng/packages/General.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<PackageVersion Include="Microsoft.Extensions.VectorData.Abstractions" Version="$(MicrosoftExtensionsVectorDataAbstractionsVersion)" />
<PackageVersion Include="Microsoft.ML.Tokenizers" Version="$(MicrosoftMLTokenizersVersion)" />
<PackageVersion Include="ModelContextProtocol.Core" Version="1.2.0" />
<PackageVersion Include="OpenAI" Version="2.10.0" />
<PackageVersion Include="OpenAI" Version="2.10.0-alpha.700" />
<PackageVersion Include="Polly" Version="8.4.2" />
<PackageVersion Include="Polly.Core" Version="8.4.2" />
<PackageVersion Include="Polly.Extensions" Version="8.4.2" />
Expand Down
4 changes: 2 additions & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"sdk": {
"version": "10.0.106"
"version": "10.0.201"
Comment thread
ericstj marked this conversation as resolved.
Outdated
},
"tools": {
"dotnet": "10.0.106",
"dotnet": "10.0.201",
"runtimes": {
"dotnet": [
"8.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using System.Threading.Tasks;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
using OpenAI;
using OpenAI.Responses;

#pragma warning disable S1226 // Method parameters, caught exceptions and foreach variables' initial values should not be ignored
Expand Down Expand Up @@ -464,6 +463,7 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) =>

case FunctionCallResponseItem fcri:
anyFunctions = true;
lastMessageId = outputItemAddedUpdate.Item.Id;
lastRole = ChatRole.Assistant;
break;
}
Expand Down Expand Up @@ -735,7 +735,9 @@ private static bool IsStoredOutputDisabled(CreateResponseOptions? options, Respo
case HostedToolSearchTool:
// Workaround: The OpenAI .NET SDK doesn't yet expose a ToolSearchTool type.
// See https://github.com/openai/openai-dotnet/issues/1053
return ModelReaderWriter.Read<ResponseTool>(BinaryData.FromString("""{"type": "tool_search"}"""), ModelReaderWriterOptions.Json, OpenAIContext.Default)!;
#pragma warning disable OPENAI001 // OpenAIResponsesContext is experimental
return ModelReaderWriter.Read<ResponseTool>(BinaryData.FromString("""{"type": "tool_search"}"""), ModelReaderWriterOptions.Json, OpenAIResponsesContext.Default)!;
#pragma warning restore OPENAI001

case HostedWebSearchTool webSearchTool:
return new WebSearchTool
Expand Down Expand Up @@ -895,7 +897,9 @@ internal static ResponseTool ToNamespaceResponseTool(string name, string? descri
writer.WriteStartArray("tools"u8);
foreach (var namespacedTool in namespacedTools)
{
var toolData = ModelReaderWriter.Write(namespacedTool, ModelReaderWriterOptions.Json, OpenAIContext.Default);
#pragma warning disable OPENAI001 // OpenAIResponsesContext is experimental
var toolData = ModelReaderWriter.Write(namespacedTool, ModelReaderWriterOptions.Json, OpenAIResponsesContext.Default);
#pragma warning restore OPENAI001
using var doc = JsonDocument.Parse(toolData);
doc.RootElement.WriteTo(writer);
}
Expand All @@ -904,7 +908,9 @@ internal static ResponseTool ToNamespaceResponseTool(string name, string? descri
writer.WriteEndObject();
}

return ModelReaderWriter.Read<ResponseTool>(BinaryData.FromBytes(stream.ToArray()), ModelReaderWriterOptions.Json, OpenAIContext.Default)!;
#pragma warning disable OPENAI001 // OpenAIResponsesContext is experimental
return ModelReaderWriter.Read<ResponseTool>(BinaryData.FromBytes(stream.ToArray()), ModelReaderWriterOptions.Json, OpenAIResponsesContext.Default)!;
#pragma warning restore OPENAI001
}

/// <summary>Creates a <see cref="ChatRole"/> from a <see cref="MessageRole"/>.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5974,6 +5974,7 @@ public async Task StreamingResponseWithFunctionCallOutput_YieldsFunctionResultCo
var functionCallUpdate = updates.FirstOrDefault(u => u.Contents.OfType<FunctionCallContent>().Any());
Assert.NotNull(functionCallUpdate);
Assert.Equal(ChatRole.Assistant, functionCallUpdate.Role);
Assert.Equal("fc_001", functionCallUpdate.MessageId); // Verify MessageID is set for function calls (issue #7479)
var fcc = functionCallUpdate.Contents.OfType<FunctionCallContent>().Single();
Assert.Equal("call_123", fcc.CallId);
Assert.Equal("get_weather", fcc.Name);
Expand All @@ -5994,14 +5995,23 @@ public async Task StreamingResponseWithFunctionCallOutput_YieldsFunctionResultCo
var response = updates.ToChatResponse();
Assert.Equal("resp_001", response.ResponseId);
Assert.Equal("gpt-4o-mini", response.ModelId);
Assert.Single(response.Messages);
var message = response.Messages[0];
Assert.Equal(ChatRole.Assistant, message.Role);

// Message should contain: FunctionCallContent, FunctionResultContent, and TextContent
Assert.Single(message.Contents.OfType<FunctionCallContent>());
Assert.Single(message.Contents.OfType<FunctionResultContent>());
var textContent = Assert.Single(message.Contents.OfType<TextContent>());
// With the MessageID fix, function calls now have their own MessageId ("fc_001") and
// the text message has a different MessageId ("msg_001"), resulting in 2 separate messages.
Assert.Equal(2, response.Messages.Count);

// First message contains the function call and result items (MessageId="fc_001")
var functionMessage = response.Messages[0];
Assert.Equal(ChatRole.Assistant, functionMessage.Role);
Assert.Equal("fc_001", functionMessage.MessageId);
Assert.Single(functionMessage.Contents.OfType<FunctionCallContent>());
Assert.Single(functionMessage.Contents.OfType<FunctionResultContent>());

// Second message contains the text response (MessageId="msg_001")
var textMessage = response.Messages[1];
Assert.Equal(ChatRole.Assistant, textMessage.Role);
Assert.Equal("msg_001", textMessage.MessageId);
var textContent = Assert.Single(textMessage.Contents.OfType<TextContent>());
Assert.Equal("It's 25°C and sunny in Paris.", textContent.Text);

// Verify usage
Expand Down
Loading