diff --git a/Directory.Packages.props b/Directory.Packages.props
index 07296dc7..97eb8f8d 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -9,9 +9,6 @@
escalated to an error by TreatWarningsAsErrors. -->
false
-
- 1.72.0
-
@@ -23,7 +20,7 @@
-
+
@@ -39,22 +36,22 @@
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
+
diff --git a/EssentialCSharp.Chat.Shared/Services/AIChatService.cs b/EssentialCSharp.Chat.Shared/Services/AIChatService.cs
index fe1bcb4d..a66bbc65 100644
--- a/EssentialCSharp.Chat.Shared/Services/AIChatService.cs
+++ b/EssentialCSharp.Chat.Shared/Services/AIChatService.cs
@@ -17,7 +17,7 @@ public partial class AIChatService
private readonly AIOptions _Options;
private readonly AzureOpenAIClient _AzureClient;
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- private readonly OpenAIResponseClient _ResponseClient;
+ private readonly ResponsesClient _ResponseClient;
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
private readonly AISearchService _SearchService;
private readonly ILogger _Logger;
@@ -34,7 +34,7 @@ public AIChatService(IOptions options, AISearchService searchService,
_AzureClient = azureClient;
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- _ResponseClient = _AzureClient.GetOpenAIResponseClient(_Options.ChatDeploymentName);
+ _ResponseClient = _AzureClient.GetResponsesClient();
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}
@@ -47,8 +47,8 @@ public AIChatService(IOptions options, AISearchService searchService,
/// Optional tools for the AI to use
/// Optional reasoning effort level for reasoning models
/// Enable vector search for contextual information
- /// Authenticated end-user identifier. Currently reserved for forwarding
- /// to Azure OpenAI for abuse monitoring once the SDK exposes ResponseCreationOptions.User.
+ /// Forwarded to Azure OpenAI for abuse monitoring and Microsoft Defender
+ /// prompt-shield correlation via CreateResponseOptions.EndUserId.
/// Cancellation token
/// The AI response text and response ID for conversation continuity
public async Task<(string response, string responseId)> GetChatCompletion(
@@ -78,8 +78,8 @@ public AIChatService(IOptions options, AISearchService searchService,
/// Optional tools for the AI to use
/// Optional reasoning effort level for reasoning models
/// Enable vector search for contextual information
- /// Authenticated end-user identifier. Currently reserved for forwarding
- /// to Azure OpenAI for abuse monitoring once the SDK exposes ResponseCreationOptions.User.
+ /// Forwarded to Azure OpenAI for abuse monitoring and Microsoft Defender
+ /// prompt-shield correlation via CreateResponseOptions.EndUserId.
/// Cancellation token
/// An async enumerable of response text chunks and final response ID
public async IAsyncEnumerable<(string text, string? responseId)> GetChatCompletionStream(
@@ -100,12 +100,10 @@ public AIChatService(IOptions options, AISearchService searchService,
// Create the streaming response using the Responses API
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- List responseItems = [ResponseItem.CreateUserMessageItem(enrichedPrompt)];
+ responseOptions.InputItems.Clear();
+ responseOptions.InputItems.Add(ResponseItem.CreateUserMessageItem(enrichedPrompt));
+ var streamingUpdates = _ResponseClient.CreateResponseStreamingAsync(responseOptions, cancellationToken);
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- var streamingUpdates = _ResponseClient.CreateResponseStreamingAsync(
- responseItems,
- options: responseOptions,
- cancellationToken: cancellationToken);
await foreach (var result in ProcessStreamingUpdatesAsync(streamingUpdates, responseOptions, mcpClient, toolCallDepth: 0, endUserId: endUserId, cancellationToken: cancellationToken))
{
@@ -181,7 +179,7 @@ private static string SanitizeForXmlContext(string? input) =>
private async IAsyncEnumerable<(string text, string? responseId)> ProcessStreamingUpdatesAsync(
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
IAsyncEnumerable streamingUpdates,
- ResponseCreationOptions responseOptions,
+ CreateResponseOptions responseOptions,
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
McpClient? mcpClient,
int toolCallDepth = 0,
@@ -247,7 +245,10 @@ private static string SanitizeForXmlContext(string? input) =>
outputItems.Add(await ExecuteSingleToolCallAsync(functionCallItem, toolCallDepth, endUserId, mcpClient, cancellationToken));
}
- var continuationStream = _ResponseClient.CreateResponseStreamingAsync(outputItems, continuationOptions, cancellationToken);
+ continuationOptions.InputItems.Clear();
+ foreach (var outputItem in outputItems)
+ continuationOptions.InputItems.Add(outputItem);
+ var continuationStream = _ResponseClient.CreateResponseStreamingAsync(continuationOptions, cancellationToken);
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
await foreach (var result in ProcessStreamingUpdatesAsync(continuationStream, continuationOptions, mcpClient, toolCallDepth + 1, endUserId, cancellationToken))
@@ -338,7 +339,7 @@ private async Task ExecuteSingleToolCallAsync(
/// Creates response options with optional features
///
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- private async Task CreateResponseOptionsAsync(
+ private async Task CreateResponseOptionsAsync(
string? systemPrompt = null,
string? previousResponseId = null,
IEnumerable? tools = null,
@@ -348,8 +349,9 @@ private async Task CreateResponseOptionsAsync(
CancellationToken cancellationToken = default
)
{
- var options = new ResponseCreationOptions();
+ var options = new CreateResponseOptions();
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+ options.Model = _Options.ChatDeploymentName;
// Set the system prompt via Instructions — this is stateless across turns when using previous_response_id,
// preventing accumulation of system messages in the conversation context.
@@ -423,7 +425,7 @@ private async Task CreateResponseOptionsAsync(
private async Task<(string response, string responseId)> GetChatCompletionCore(
string prompt,
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- ResponseCreationOptions responseOptions,
+ CreateResponseOptions responseOptions,
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
McpClient? mcpClient = null,
string? endUserId = null,
@@ -436,13 +438,13 @@ private async Task CreateResponseOptionsAsync(
const int MaxToolCallIterations = 10;
for (int iteration = 0; iteration < MaxToolCallIterations; iteration++)
{
- ClientResult response;
+ ClientResult response;
try
{
- response = await _ResponseClient.CreateResponseAsync(
- responseItems,
- options: responseOptions,
- cancellationToken: cancellationToken);
+ responseOptions.InputItems.Clear();
+ foreach (var responseItem in responseItems)
+ responseOptions.InputItems.Add(responseItem);
+ response = await _ResponseClient.CreateResponseAsync(responseOptions, cancellationToken);
}
catch (ClientResultException ex) when (IsContextLengthError(ex))
{
@@ -532,16 +534,16 @@ private bool IsMcpToolAllowed(string toolName)
///
/// Returns a clone of with
- /// replaced.
+ /// replaced.
/// All behavior-affecting properties are copied so that tool-call continuation legs
/// produce identical generation behavior to the initial leg.
///
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- private static ResponseCreationOptions CloneOptionsWithPreviousResponseId(
- ResponseCreationOptions source,
+ private static CreateResponseOptions CloneOptionsWithPreviousResponseId(
+ CreateResponseOptions source,
string? previousResponseId)
{
- var clone = new ResponseCreationOptions
+ var clone = new CreateResponseOptions
{
Instructions = source.Instructions,
PreviousResponseId = previousResponseId,