Commit Graph

3 Commits

  • .NET: Bump MEAI to 10.5.1 and add Foundry per-call x-client header support (#5652)
    * Bump MEAI to 10.5.1 and add per-call x-client header support
    
    Replaces the brittle UserAgentResponsesClient subclass with a clean
    per-call x-client-* header pipeline built on the new Microsoft.Extensions.AI
    10.5.1 OpenAIRequestPolicies hook.
    
    Public surface (Microsoft.Agents.AI.Foundry, [Experimental(MAAI001)]):
    * chatOptions.WithClientHeader(name, value) and .WithClientHeaders(IEnumerable)
      validate the x-client- prefix (case-insensitive), apply all-or-nothing on
      bulk, and throw InvalidOperationException on foreign-typed slot collision
    * myAgent.AsBuilder().UseClientHeaders().Build() opts a customer-built agent
      into the pipeline; idempotent via agent.GetService<ClientHeadersAgent>()
    * Foundry-built agents (FoundryAgent.Create*) pre-wire automatically
    
    Internals:
    * ClientHeadersAgent decorator snapshots the dict at scope-push time so
      concurrent runs sharing a ChatOptions reference do not leak headers
    * ClientHeadersScope is an AsyncLocal<IReadOnlyDictionary<string,string>?>
      with LIFO push/dispose semantics
    * ClientHeadersPolicy singleton stamps headers via Headers.Set so per-call
      values overwrite any same-name header from earlier policies and so
      duplicate registration is value-stable
    * OpenAIRequestPoliciesReflection dedups against MEAI's private _entries
      field and falls back to AddPolicy on any reflection failure; a CI test
      asserts the field shape on every MEAI bump
    
    Hosting cleanup:
    * Deleted UserAgentResponsesClient and its dummy throwing pipeline
    * HostedAgentUserAgentPolicy is now registered via OpenAIRequestPolicies
      in FoundryHostingExtensions.TryApplyUserAgent
    
    Tests:
    * 19 new unit tests in ClientHeadersExtensionsTests.cs covering validation,
      AsyncLocal isolation, snapshot semantics, end-to-end wire stamping, and
      shared-chat-client dedup
    * Updated OpenTelemetryAgentTests for MEAI 10.5.1 changes to web_search
      serialization and the reduced tool definition payload when sensitive
      data capture is disabled
    
    Microsoft.Extensions.Compliance.Abstractions stays at 10.5.0 because no
    10.5.1 release exists on nuget.org.
    
    * Address PR review: pre-wire AsAIAgent path and dedup TryApplyUserAgent
    
    * FoundryAgent: extract WireClientHeaders helper and call it from the
      internal (AIProjectClient, ChatClientAgent) constructor used by
      AzureAIProjectChatClientExtensions.AsAIAgent so those Foundry-built
      agents also pre-wire the x-client header pipeline.
    * Foundry.Hosting TryApplyUserAgent: dedup HostedAgentUserAgentPolicy
      registration per OpenAIRequestPolicies instance via
      ConditionalWeakTable so per-request resolution does not grow the
      policy list unboundedly on singleton agents.
    
    * Add tests covering AsAIAgent pre-wire and TryApplyUserAgent dedup
    
    Backs the PR review fixes from a4c8f91 with regression tests:
    * ClientHeadersExtensionsTests: AsAIAgent_FoundryAgent_HasPreWiredClientHeadersAgent
      asserts the FoundryAgent built via AzureAIProjectChatClientExtensions.AsAIAgent
      contains a ClientHeadersAgent in its delegating chain (catches future
      regressions of the bypass).
    * ClientHeadersExtensionsTests: FoundryAgent_PublicConstructor_HasPreWiredClientHeadersAgent
      covers the public constructor path the same way.
    * ClientHeadersExtensionsTests: UseClientHeaders_RepeatedRegistrations_OnSameChatClient_OnlyRegistersOnce
      invokes UseClientHeaders 25 times on a shared chat client and asserts via
      reflection that OpenAIRequestPolicies._entries length is exactly 1.
    * HostedTryApplyUserAgentDedupTests: two tests asserting
      FoundryHostingExtensions.TryApplyUserAgent stays at one entry per
      OpenAIRequestPolicies instance after 50 calls on the same agent and across
      distinct agents on different chat clients.
    
    * Move tests next to their SUT
    
    Removes the dedicated HostedTryApplyUserAgentDedupTests.cs test class.
    Tests are co-located with the SUT they exercise:
    
    * FoundryAgentTests.cs gains the Constructor_PreWiresClientHeadersAgent
      and Constructor_FromAsAIAgentExtension_PreWiresClientHeadersAgent
      cases, since FoundryAgent is the SUT for the pre-wire behavior.
    * HostedOutboundUserAgentTests.cs gains the two TryApplyUserAgent dedup
      cases, since FoundryHostingExtensions.TryApplyUserAgent is the SUT
      it already covers.
    * ClientHeadersExtensionsTests.cs keeps only the
      UseClientHeaders_RepeatedRegistrations_OnSameChatClient_OnlyRegistersOnce
      case, which exercises the public ClientHeadersExtensions surface.
    
    * Remove redundant WithCancellation on inner streaming call
    
    ct is already passed to InnerAgent.RunStreamingAsync, so
    .WithCancellation(ct) on the resulting IAsyncEnumerable is a no-op.
    Caught by Sergey on PR review.
    
    * Address PR review: surface downstream MEAI experimental ID
    
    * Add AIOpenAIRequestPolicies = MEAIExperiments alias to
      DiagnosticIds.Experiments (matches the existing AIResponseContinuations,
      AIMcpServers, AIFunctionApprovals pattern).
    * Mark public ClientHeadersExtensions with [Experimental(AIOpenAIRequestPolicies)]
      instead of AgentsAIExperiments. Consumers now see the MEAI001 warning,
      surfacing the dependency on MEAI's experimental OpenAIRequestPolicies hook.
    * Mark internal OpenAIRequestPoliciesReflection with the same alias to
      suppress warnings at the source rather than via project-wide NoWarn.
    * Remove MEAI001 from Foundry csproj NoWarn (kept on Foundry.Hosting where
      pre-PR usages remain).
    * Clarify ClientHeadersScope XML doc: AsyncLocal flows values forward but
      does NOT auto-restore on method return; explicit using/Dispose is what
      gives stack-style LIFO semantics.
  • Add CreateSessionAsync(conversationId) to FoundryAgent (#5144)
    Adds a public CreateSessionAsync(string conversationId, CancellationToken)
    method to FoundryAgent that delegates to the inner ChatClientAgent,
    allowing users to create sessions with existing server-side conversation IDs.
    
    Fixes #5138
  • .NET: Rename Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry and consolidate FoundryMemory (#5042)
    * Update Foundry Responses as ChatClientAgent
    
    * Migrate obsolete AzureAI integration tests to versioned agent pattern
    
    Replace obsolete CreateAIAgentAsync/GetAIAgentAsync calls with
    Agents.CreateAgentVersionAsync() + AsAIAgent(AgentVersion) in all
    AzureAI integration tests.
    
    - Rename AIProjectClient* test files to FoundryVersionedAgent*
    - Register AIFunction tools in PromptAgentDefinition.Tools for
      server-side visibility via AsOpenAIResponseTool()
    - Skip structured output tests (AzureAIProjectChatClient clears
      ResponseFormat for versioned agents)
    - Remove all [Obsolete] attributes and #pragma warning disable CS0618
    
    * Merge FoundryMemory package into AzureAI under Memory/ folder
    
    Move all FoundryMemory source, unit tests, and integration tests into
    the Microsoft.Agents.AI.AzureAI package. Change namespace from
    Microsoft.Agents.AI.FoundryMemory to Microsoft.Agents.AI.AzureAI.
    
    - Add [Experimental] to FoundryMemoryProviderOptions and Scope
    - Rename internal AIProjectClientExtensions to MemoryStoreExtensions
    - Update AzureAI .csproj with Compliance.Abstractions, Redaction
    - Remove FoundryMemory from solution and release filter
    - Update sample to reference AzureAI instead of FoundryMemory
    - Delete old Microsoft.Agents.AI.FoundryMemory project and tests
    
    * Add EnsureMemoryStoreCreatedAsync and memory existence checks to integration tests
    
    - Ensure memory store is created before testing memory operations
    - Add AZURE_AI_EMBEDDING_DEPLOYMENT_NAME config setting
    - Assert memories exist in store via SearchMemoriesAsync before cleanup
    - Verify scope isolation with direct memory store queries
    
    * Fix and rename AzureAI unit tests for RAPI vs Versioned clarity
    
    - Rename AsAIAgentAsync_* to AsAIAgent_* (drop Async from method group)
    - Add _Rapi_ prefix to non-versioned (Responses API) tests
    - Add _Versioned_ prefix to versioned agent tests where needed
    - Fix RAPI tests: assert GetService<AIProjectClient>() is null
    - Fix Versioned tests: assert IsType<FoundryAgent> and
      GetService<AIProjectClient>() returns the client instance
    - Fix UserAgent header tests: proper HTTP handler routing
    - Fix ChatClient_UsesDefaultConversationIdAsync test setup
    - All 153 unit tests pass with 0 failures
    
    * Rename Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry
    
    Rename the project, namespace, folder, and all references from
    Microsoft.Agents.AI.AzureAI to Microsoft.Agents.AI.Foundry.
    Also rename Workflows.Declarative.AzureAI to .Foundry.
    
    - Rename src, unit test, integration test, and workflow folders
    - Update namespaces in all source and test .cs files
    - Update ProjectReferences in ~47 sample and test .csproj files
    - Update solution files (.slnx, .slnf)
    - Update sample using statements
    - Update READMEs, SKILL.md, ADRs in docs/
    - Disable package validation baseline for renamed packages
    - Fix UTF-8 BOM encoding on all affected .cs files
    - AzureAI.Persistent left completely unchanged
    
    * Fix format: remove ImplicitUsings, add explicit usings, fix BOM encoding
    
    - Remove ImplicitUsings=enable from Foundry csproj to resolve IDE0005
      on shared ReplacingRedactor.cs
    - Add explicit System usings to all source files that relied on them
    - Sort usings alphabetically per editorconfig rules
    - Fix UTF-8 BOM on 12 sample Program.cs files
    - Rename Azure AI Foundry Agents to Microsoft Foundry Agents in docs