// Copyright (c) Microsoft. All rights reserved. using System.ClientModel.Primitives; using System.Collections.Generic; using System.Threading.Tasks; namespace Microsoft.Agents.AI.Foundry; /// /// Pipeline policy that captures the x-ms-served-model response header from Azure OpenAI /// and stores it in for consumption by . /// /// /// /// Azure OpenAI Responses API returns the deployment alias in response.model but the actual /// model snapshot (e.g. gpt-5-nano-2025-08-07) in the x-ms-served-model response header. /// This policy extracts the header after the HTTP roundtrip so the /// can overwrite ChatResponse.ModelId with the true model name. /// /// /// Registered once per OpenAIRequestPolicies instance via the MEAI 10.5.1 extension hook. /// When the header is absent (non-Azure endpoints), the scope is not set and the /// preserves the original model name. /// /// internal sealed class ServedModelPolicy : PipelinePolicy { /// The Azure OpenAI response header that carries the actual served model name. internal const string ServedModelHeader = "x-ms-served-model"; public static ServedModelPolicy Instance { get; } = new ServedModelPolicy(); private ServedModelPolicy() { } public override void Process(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) { ProcessNext(message, pipeline, currentIndex); CaptureServedModel(message); } public override async ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) { await ProcessNextAsync(message, pipeline, currentIndex).ConfigureAwait(false); CaptureServedModel(message); } private static void CaptureServedModel(PipelineMessage message) { if (message.Response is null) { return; } if (message.Response.Headers.TryGetValue(ServedModelHeader, out string? servedModel) && !string.IsNullOrWhiteSpace(servedModel)) { // Write into the box (reference-type mutation) so the value is visible to the // FoundryChatClient that pushed the box before calling the inner client. if (ServedModelScope.Current is { } box) { box.Value = servedModel.Trim(); } } } }