// 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.");
}
}