// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Azure.AI.Extensions.OpenAI; using Azure.AI.Projects.Agents; using Microsoft.Extensions.AI; using Microsoft.Shared.Diagnostics; using OpenAI.Files; using OpenAI.VectorStores; #pragma warning disable OPENAI001 namespace Microsoft.Agents.AI.Foundry; /// /// Foundry-specific extensions on . Hosts the prompt-agent converter /// plus thin forwarders that surface the file and vector-store helpers from the inner /// at the agent level so callers do not need to drop down to /// agent.GetService<FoundryChatClient>().X() for common workflows. /// public static class FoundryAgentExtensions { /// /// Converts the supplied into a /// ready to publish via AgentAdministrationClient.CreateAgentVersionAsync. /// /// /// The Agent Endpoint construction mode (Mode 3) is not convertible because no local /// definition exists; conversion in that case throws . /// /// The Foundry agent to convert. /// A token that can cancel an internal server-side fetch when the agent was constructed from a bare . /// A suitable for publishing. /// is . /// The agent's chat client is not a ; the agent was constructed via the Agent Endpoint mode (Mode 3); no model id is set on the agent's for the Responses Agent mode (Mode 1); or the agent contains an that cannot be converted to a ResponseTool. public static Task ToPromptAgentAsync(this FoundryAgent agent, CancellationToken cancellationToken = default) { Throw.IfNull(agent); var innerChatClient = agent.GetService() ?? throw new InvalidOperationException( "ToPromptAgentAsync could not resolve the inner IChatClient on the FoundryAgent."); var chatOptions = agent.GetService(); return FoundryPromptAgentConverter.ConvertAsync(innerChatClient, chatOptions, cancellationToken); } /// /// Uploads a file to the project. Thin forwarder to /// /// on the agent's inner . /// /// The Foundry agent whose inner chat client owns the upload pipeline. /// Path to the file to upload. /// The upload purpose (e.g. ). /// A token that can cancel the upload. /// is . /// The agent does not expose a via . public static Task UploadFileAsync(this FoundryAgent agent, string filePath, FileUploadPurpose purpose, CancellationToken cancellationToken = default) => RequireFoundryChatClient(agent).UploadFileAsync(filePath, purpose, cancellationToken); /// /// Deletes a previously uploaded file. Thin forwarder to /// . /// /// The Foundry agent whose inner chat client owns the file pipeline. /// The file id returned by . /// A token that can cancel the delete. /// is . /// The agent does not expose a . public static Task DeleteFileAsync(this FoundryAgent agent, string fileId, CancellationToken cancellationToken = default) => RequireFoundryChatClient(agent).DeleteFileAsync(fileId, cancellationToken); /// /// Uploads the supplied files, creates a vector store containing them, and waits until the /// store leaves the in-progress state. Thin forwarder to /// . /// /// The Foundry agent whose inner chat client owns the file and vector-store pipeline. /// The vector store name. /// Paths to files to upload and attach to the store. /// Optional last-active-at expiration window. /// Optional upper bound on the wait for the vector store to leave the in-progress state. Defaults to 5 minutes; pass to disable. /// A token that can cancel the orchestration. /// is . /// The agent does not expose a . /// The vector store did not leave the in-progress state within . public static Task CreateVectorStoreAsync(this FoundryAgent agent, string name, IEnumerable filePaths, TimeSpan? expiresAfter = null, TimeSpan? pollingTimeout = null, CancellationToken cancellationToken = default) => RequireFoundryChatClient(agent).CreateVectorStoreAsync(name, filePaths, expiresAfter, pollingTimeout, cancellationToken); /// /// Deletes a vector store. Thin forwarder to /// . /// /// The Foundry agent whose inner chat client owns the vector-store pipeline. /// The vector store id. /// A token that can cancel the delete. /// is . /// The agent does not expose a . public static Task DeleteVectorStoreAsync(this FoundryAgent agent, string vectorStoreId, CancellationToken cancellationToken = default) => RequireFoundryChatClient(agent).DeleteVectorStoreAsync(vectorStoreId, cancellationToken); private static FoundryChatClient RequireFoundryChatClient(FoundryAgent agent) { Throw.IfNull(agent); return agent.GetService() ?? throw new InvalidOperationException( "FoundryAgent does not expose a FoundryChatClient via GetService(). " + "File and vector-store helpers require the agent's inner chat client to be a FoundryChatClient."); } }