You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Address PR #5940 design feedback (Q-A through Q-F)
Q-A: poll vector store til status leaves InProgress before return. Exp backoff 250ms-2s. Honor cancel.
Q-B: try/catch upload loop. Mid-fail = best-effort DeleteFileAsync on already-uploaded ids. Swallow cleanup errors.
Q-C: pinned AgentReference.Version uses GetAgentVersionAsync. Empty/whitespace/'latest' = GetLatest path.
Q-D: HostedAgentUserAgentPolicy detects existing combined 'foundry-hosting/...' segment. No double prefix.
Q-E: mode-3 vector-store test uses fake transport. No DNS to example.com.
Q-F: no shim. Class always [Experimental] (since 8015e00, before dotnet-1.0.0). No compat contract. Callers rename to AIProjectClientExtensions.
Rebase onto origin/main reconciliation: aad20c2 added public AsAIAgent(this AIProjectClient, Uri agentEndpoint, ...) extension that calls an internal FoundryAgent(AIProjectClient, Uri, ...) ctor. Reintroduced that ctor + a new FoundryChatClient(AIProjectClient, Uri, ProjectOpenAIClientOptions?) overload that reuses the supplied AIProjectClient's pipeline (via GetProjectResponsesClientForAgentEndpoint) instead of stamping a fresh credential.
Verified: 346/346 net10 + 284/284 net472 Foundry unit, 230/230 Foundry.Hosting unit, format clean.
Copy file name to clipboardExpand all lines: dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/HostedAgentUserAgentPolicy.cs
+24-1Lines changed: 24 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -43,6 +43,9 @@ internal sealed class HostedAgentUserAgentPolicy : PipelinePolicy
43
43
/// <summary>Bare segment stamped by <c>AgentFrameworkUserAgentPolicy</c> in the non-hosted scenario; this policy upgrades it in-place when both run.</summary>
/// <summary>Combined hosted segment that this policy emits. Recognized in-place so callers whose pipelines already carry a (possibly different-version) combined segment get it replaced rather than double-prefixed (Q-D fix).</summary>
/// Internal constructor used by <c>AsAIAgent</c> extension methods that already have an <see cref="AIProjectClient"/> and a configured <see cref="ChatClientAgent"/>.
/// <param name="name">The vector store name.</param>
265
281
/// <param name="filePaths">Paths to files to upload and attach to the store.</param>
266
282
/// <param name="expiresAfter">Optional last-active-at expiration window. When supplied, the vector store expires this many days after its last use.</param>
267
283
/// <param name="cancellationToken">A token that can cancel the orchestration.</param>
268
-
/// <returns>The created and fully-ready <see cref="VectorStore"/>.</returns>
284
+
/// <returns>The created and fully-ready <see cref="VectorStore"/>. The returned instance reflects the state observed after polling completes; it may be in <see cref="VectorStoreStatus.Completed"/> (typical), <see cref="VectorStoreStatus.Expired"/>, or any other terminal status returned by the service. Only <see cref="VectorStoreStatus.InProgress"/> is polled.</returns>
285
+
/// <remarks>
286
+
/// <para>
287
+
/// File-upload semantics are best-effort: when one of the per-file uploads throws, this method
288
+
/// makes a best-effort attempt to delete the files it has already uploaded so they do not
289
+
/// accumulate as orphaned resources on the project, then rethrows the original exception. The
290
+
/// cleanup itself does not throw — its failures are silently ignored because the caller is
291
+
/// already receiving a more meaningful exception from the original upload failure.
292
+
/// </para>
293
+
/// <para>
294
+
/// Cancellation aborts the polling loop with an <see cref="OperationCanceledException"/>; any
295
+
/// already-uploaded files and the partially-created vector store remain on the project and are
296
+
/// the caller's responsibility to clean up.
297
+
/// </para>
298
+
/// </remarks>
269
299
/// <exception cref="ArgumentException"><paramref name="name"/> is <see langword="null"/> or whitespace, or <paramref name="filePaths"/> is <see langword="null"/>.</exception>
/// <summary>Deletes a vector store. The associated files (if any) are not deleted by this method; call <see cref="DeleteFileAsync(string, CancellationToken)"/> separately to clean them up.</summary>
/// <summary>Best-effort registration of <see cref="AgentFrameworkUserAgentPolicy"/> via the MEAI <see cref="OpenAIRequestPolicies"/> hook with at-most-once dedup per pipeline.</summary>
0 commit comments