mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
ece3db8cfde14654d5609e255cf4e07cb533a52e
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ad95f2f2fa |
.NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) (#5702)
* .NET: Add Hosted-MemoryAgent sample with isolation key plumbing (#5692) Adds HostedSessionContext + HostedSessionIsolationKeyProvider in Microsoft.Agents.AI.Foundry.Hosting so AIContextProviders (notably FoundryMemoryProvider) can scope per user via the platform's x-agent-user-isolation-key / x-agent-chat-isolation-key headers. - New types: HostedSessionContext (sealed), HostedSessionContextExtensions (public Get, internal Set), abstract HostedSessionIsolationKeyProvider (async), internal PlatformHostedSessionIsolationKeyProvider mapping ResponseContext.Isolation. - AgentFrameworkResponseHandler now resolves the provider, tags fresh sessions, and validates resumed sessions against the live request (strict 403 'Hosted session identity context mismatch' on any mismatch; 500 on null keys). - New shared sample project Hosted_Shared_Contributor_Setup hosts DevTemporaryTokenCredential and DevTemporaryLocalSessionIsolationKeyProvider plus AddDevTemporaryLocalContributorSetup. All 9 existing responses samples migrated to consume it so local runs keep working under the strict isolation contract. - New Hosted-MemoryAgent sample: travel assistant wired through FoundryMemoryProvider with stateInitializer reading session.GetHostedContext().UserId. Includes Dockerfile, smoke.ps1, agent.yaml/manifest. - New IT scenario 'memory' in Foundry.Hosting.IntegrationTests + MemoryHostedAgentFixture + MemoryHostedAgentTests. Verified end to end against the tao Foundry project. - ADR 0026 captures the design tree. * Address PR review feedback - Dockerfile: add header noting it targets NuGet builds; contributors must use Dockerfile.contributor for ProjectReference source builds. - PlatformHostedSessionIsolationKeyProvider: doc said 'returns context with empty values'; corrected to 'returns null' which the handler treats as 500. - FakeHostedSessionIsolationKeyProvider: doc clarifies that null configurations are allowed for testing the handler error path. - HostedSessionContextExtensions.SetHostedContext: enforce write-once with InvalidOperationException; doc + xml exception updated. - AgentFrameworkResponseHandler: cache PlatformHostedSessionIsolationKeyProvider as static readonly to avoid per-request allocation. - MemoryHostedAgentTests: tighten waits from 20s to 5s (FoundryMemoryProvider defaults UpdateDelay=0; ingestion ~3s). - Sample Program.cs imports reordered to satisfy IDE0005. * Add HostedFoundryMemoryProviderScopes built-in helpers (#5692) Addresses review feedback from @lokitoth on Hosted-MemoryAgent/Program.cs:54. - New HostedFoundryMemoryProviderScopes static class with PerUser, PerChat, PerUserAndChat factories returning Func<AgentSession?, FoundryMemoryProvider.State>. - All helpers throw InvalidOperationException when GetHostedContext() is null, with a message pointing at writing a custom stateInitializer for non-hosted scenarios. - New HostedFoundryMemoryScope enum and AddHostedFoundryMemoryProvider DI extension (two overloads: explicit AIProjectClient and DI-resolved). Singleton lifetime. Default scope = PerUser. - Hosted-MemoryAgent sample and the memory IT scenario container both swap their inline lambdas for HostedFoundryMemoryProviderScopes.PerUser(). - 14 new unit tests (241/241 hosting unit tests pass). * Replace HostedFoundryMemoryScope enum with Func<...> parameter (#5692) Address PR review feedback from @westey-m: enums are a breaking-change hazard when extended, and the enum was redundant with the existing HostedFoundryMemoryProviderScopes static class. - Delete HostedFoundryMemoryScope.cs. - AddHostedFoundryMemoryProvider DI extensions now take Func<AgentSession?, FoundryMemoryProvider.State>? stateInitializer = null. When null, default to HostedFoundryMemoryProviderScopes.PerUser(). - Callers pick a built-in helper (PerUser/PerChat/PerUserAndChat) or pass a custom delegate. New built-ins are a single static method addition with zero impact on existing callers. - Tests updated; 244/244 hosting unit tests pass. * Fix isolation context resume for externally-created conversations (#5692) Branch on the session's existing hosted-context (not on conversation_id presence) so a conversation provisioned externally (e.g. via conversations.CreateProjectConversationAsync) is treated as fresh on first hosted-agent request and stamped, rather than rejected with 403 hosted_session_identity_mismatch. Strict equality is preserved on real resume of an already-stamped session. Also tighten dotnet/global.json to version 10.0.204 + rollForward latestPatch so local builds match the CI Docker image SDK and avoid 10.0.300 dotnet format stripping required usings. * Revert global.json SDK pin to upstream (#5692) The 10.0.204 + latestPatch pin from the previous commit broke the dotnet-format CI job (hostfxr_resolve_sdk2 could not find a compatible SDK in the mcr.microsoft.com/dotnet/sdk:10.0 image). Restore upstream 10.0.200 + minor; local Release builds with SDK 10.0.300 should set GITHUB_ACTIONS=true to bypass the auto-format-on-build target. |
||
|
|
b12109b7e4 |
.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
|
||
|
|
fb97e93a01 |
.NET: Add dedicated Foundry.Hosting UnitTest project (#5592)
* Foundry.Hosting.UnitTests: extract project from Foundry.UnitTests Move all Hosting/* tests, three toolbox TestData JSONs, and the FakeAuthenticationTokenProvider/HttpHandlerAssert/TestDataUtil helpers (trimmed to toolbox getters) into a new Microsoft.Agents.AI.Foundry.Hosting.UnitTests project. Add it to the slnx and grant the new assembly InternalsVisibleTo from Microsoft.Agents.AI.Foundry and Microsoft.Agents.AI.Foundry.Hosting. * Foundry.Hosting.UnitTests: align namespaces to assembly name Rename namespaces from Microsoft.Agents.AI.Foundry.UnitTests(.Hosting) to Microsoft.Agents.AI.Foundry.Hosting.UnitTests across all moved tests, the duplicated helpers, and the trimmed TestDataUtil. Also fixes the prior namespace inconsistency in FoundryToolboxTests. * Foundry.Hosting.UnitTests: split WorkflowIntegrationTests by SUT Replace the WorkflowIntegrationTests file (an IT-named file inside a UT project) with two SUT-focused files plus a shared test-doubles file: - AgentFrameworkResponseHandlerWorkflowTests.cs - the 5 handler-driven tests that exercise AgentFrameworkResponseHandler with a real workflow agent. - OutputConverterWorkflowTests.cs - the 5 OutputConverter tests driven by hand-crafted update sequences mirroring real workflow patterns. - WorkflowTestAgents.cs - StreamingTextAgent and ThrowingStreamingAgent extracted as internal types used by both files. * Foundry.UnitTests: trim Hosting-related conditionals and dead testdata Now that Hosting tests live in their own project: - drop the Compile Remove guard for the Hosting subfolder, - drop the .NETCoreApp-only PackageReferences (Azure.AI.AgentServer.Responses, Microsoft.AspNetCore.TestHost, OpenTelemetry, OpenTelemetry.Exporter.InMemory), - drop the conditional ProjectReference to Microsoft.Agents.AI.Foundry.Hosting, - delete the three Toolbox JSON files and the matching Toolbox getters in TestDataUtil. * Foundry.Hosting.UnitTests: drop redundant 'using Microsoft.Agents.AI.Foundry.Hosting' The new project namespace is Microsoft.Agents.AI.Foundry.Hosting.UnitTests, which already brings the parent Microsoft.Agents.AI.Foundry.Hosting namespace into scope. The explicit using statement is therefore redundant (IDE0005). Caught by 'dotnet format --verify-no-changes' running on Linux against the .NET 10 SDK. * Foundry.Hosting: drop InternalsVisibleTo to Foundry.UnitTests The non-hosting Foundry.UnitTests project no longer holds any Hosting tests after the split, so it doesn't need access to internal types in Microsoft.Agents.AI.Foundry.Hosting. Only Microsoft.Agents.AI.Foundry.Hosting.UnitTests needs it. * Foundry.Hosting: rename DelegatingResponsesClient to UserAgentResponsesClient Address westey-m's review feedback on PR #5453: `Delegating*` is conventionally reserved for inheritable base classes (mirroring `DelegatingHandler`) where consumers override one or two members. This polyfill is sealed and only injects the User-Agent supplement, so the new name reflects its actual purpose. Renamed via `git mv` to preserve history: * `src/Microsoft.Agents.AI.Foundry.Hosting/DelegatingResponsesClient.cs` to `UserAgentResponsesClient.cs` * `tests/Microsoft.Agents.AI.Foundry.Hosting.UnitTests/DelegatingResponsesClientTests.cs` to `UserAgentResponsesClientTests.cs` Class, constructor, and all references updated across: * `src/.../UserAgentResponsesClient.cs` (class + constructor + internal log message) * `src/.../ServiceCollectionExtensions.cs` (cref + type check + instantiation) * `src/.../HostedAgentUserAgentPolicy.cs` (cref) * `tests/Foundry.UnitTests/RequestOptionsExtensionsTests.cs` (comment) * `tests/Foundry.Hosting.UnitTests/UserAgentResponsesClientTests.cs` (class + cref + instantiations) |