mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
5fe8941ff9
* dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 breaking changes Add FoundryToolbox and AIProjectClient extensions to Microsoft.Agents.AI.Foundry.Hosting for server-side toolbox tool integration matching Python's FoundryChatClient.get_toolbox() pattern. Tools are fetched from the Foundry project SDK and passed as server-side tools in the Responses API request. New files: - FoundryToolbox.cs: Core implementation using AgentAdministrationClient SDK - AIProjectClientToolboxExtensions.cs: Extension methods on AIProjectClient - Agent_Step25_ToolboxServerSideTools sample with create helper and combine flow - 19 unit tests covering param validation, conversion, sanitization, and extensions SDK breaking changes (Azure.AI.AgentServer.Responses beta.3 -> beta.4): - FunctionToolCallOutputResource renamed to OutputItemFunctionToolCallOutput - AzureAIAgentServerResponsesModelFactory made internal, replaced with direct constructors - ResponseUsage constructor now requires non-null token details parameters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: reuse endpoint variable in CreateSampleToolboxAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: pass endpoint through static local functions to avoid capture Static local functions cannot capture top-level variables. Thread the endpoint parameter through Main, CombineToolboxes, and CreateSampleToolboxAsync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: remove unused projectClient param from CreateSampleToolboxAsync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Removing GetToolbocVersion. * Removing tests for GetToolboxVersion * fix: map cached/reasoning token counts in ConvertUsage instead of hardcoding zeros Extract InputTokenDetails.CachedTokenCount and OutputTokenDetails.ReasoningTokenCount from UsageDetails.AdditionalCounts, matching the pattern in AgentResponseExtensions. Also accumulate detail counts when merging with existing usage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: alliscode <bentho@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
184 lines
8.4 KiB
C#
184 lines
8.4 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System.ClientModel.Primitives;
|
|
using System.IO;
|
|
using Azure.AI.Projects.Agents;
|
|
|
|
namespace Microsoft.Agents.AI.Foundry.UnitTests;
|
|
|
|
/// <summary>
|
|
/// Utility class for loading and processing test data files.
|
|
/// </summary>
|
|
internal static class TestDataUtil
|
|
{
|
|
private static readonly string s_agentResponseJson = File.ReadAllText("TestData/AgentResponse.json");
|
|
private static readonly string s_agentVersionResponseJson = File.ReadAllText("TestData/AgentVersionResponse.json");
|
|
private static readonly string s_openAIDefaultResponseJson = File.ReadAllText("TestData/OpenAIDefaultResponse.json");
|
|
private static readonly string s_toolboxRecordResponseJson = File.ReadAllText("TestData/ToolboxRecordResponse.json");
|
|
private static readonly string s_toolboxVersionResponseJson = File.ReadAllText("TestData/ToolboxVersionResponse.json");
|
|
private static readonly string s_toolboxVersionWithDecorationFieldsJson = File.ReadAllText("TestData/ToolboxVersionWithDecorationFields.json");
|
|
|
|
private const string AgentDefinitionPlaceholder = "\"agent-definition-placeholder\"";
|
|
|
|
private const string DefaultAgentDefinition = """
|
|
{
|
|
"kind": "prompt",
|
|
"model": "gpt-5-mini",
|
|
"instructions": "You are a storytelling agent. You craft engaging one-line stories based on user prompts and context.",
|
|
"tools": []
|
|
}
|
|
""";
|
|
|
|
/// <summary>
|
|
/// Gets the agent response JSON with optional placeholder replacements applied.
|
|
/// </summary>
|
|
public static string GetAgentResponseJson(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
return json;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the agent version response JSON with optional placeholder replacements applied.
|
|
/// </summary>
|
|
public static string GetAgentVersionResponseJson(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentVersionResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
return json;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the agent version response JSON with empty version and ID fields for testing hosted agents like MCP agents.
|
|
/// </summary>
|
|
public static string GetAgentVersionResponseJsonWithEmptyVersion(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentVersionResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
// Remove the version and id fields to simulate hosted agents without version
|
|
json = json.Replace("\"version\": \"1\",", "\"version\": \"\",")
|
|
.Replace("\"id\": \"agent_abc123:1\",", "\"id\": \"\",");
|
|
return json;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the agent response JSON with empty version and ID fields in the latest version for testing hosted agents like MCP agents.
|
|
/// </summary>
|
|
public static string GetAgentResponseJsonWithEmptyVersion(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
// Remove the version and id fields to simulate hosted agents without version
|
|
json = json.Replace("\"version\": \"1\",", "\"version\": \"\",")
|
|
.Replace("\"id\": \"agent_abc123:1\",", "\"id\": \"\",");
|
|
return json;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the agent version response JSON with whitespace-only version and ID fields for testing hosted agents like MCP agents.
|
|
/// </summary>
|
|
public static string GetAgentVersionResponseJsonWithWhitespaceVersion(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentVersionResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
// Use whitespace-only version and id fields to simulate hosted agents without version
|
|
return json
|
|
.Replace("\"version\": \"1\",", "\"version\": \" \",")
|
|
.Replace("\"id\": \"agent_abc123:1\",", "\"id\": \" \",");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the agent response JSON with whitespace-only version and ID fields in the latest version for testing hosted agents like MCP agents.
|
|
/// </summary>
|
|
public static string GetAgentResponseJsonWithWhitespaceVersion(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_agentResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
// Use whitespace-only version and id fields to simulate hosted agents without version
|
|
return json
|
|
.Replace("\"version\": \"1\",", "\"version\": \" \",")
|
|
.Replace("\"id\": \"agent_abc123:1\",", "\"id\": \" \",");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the OpenAI default response JSON with optional placeholder replacements applied.
|
|
/// </summary>
|
|
public static string GetOpenAIDefaultResponseJson(string? agentName = null, ProjectsAgentDefinition? agentDefinition = null, string? instructions = null, string? description = null)
|
|
{
|
|
var json = s_openAIDefaultResponseJson;
|
|
json = ApplyAgentName(json, agentName);
|
|
json = ApplyAgentDefinition(json, agentDefinition);
|
|
json = ApplyInstructions(json, instructions);
|
|
json = ApplyDescription(json, description);
|
|
return json;
|
|
}
|
|
|
|
private static string ApplyAgentName(string json, string? agentName)
|
|
{
|
|
if (!string.IsNullOrEmpty(agentName))
|
|
{
|
|
return json.Replace("\"agent_abc123\"", $"\"{agentName}\"");
|
|
}
|
|
return json;
|
|
}
|
|
|
|
private static string ApplyAgentDefinition(string json, ProjectsAgentDefinition? definition)
|
|
{
|
|
return (definition is not null)
|
|
? json.Replace(AgentDefinitionPlaceholder, ModelReaderWriter.Write(definition).ToString())
|
|
: json.Replace(AgentDefinitionPlaceholder, DefaultAgentDefinition);
|
|
}
|
|
|
|
private static string ApplyInstructions(string json, string? instructions)
|
|
{
|
|
if (!string.IsNullOrEmpty(instructions))
|
|
{
|
|
return json.Replace("You are a storytelling agent. You craft engaging one-line stories based on user prompts and context.", instructions);
|
|
}
|
|
return json;
|
|
}
|
|
|
|
private static string ApplyDescription(string json, string? description)
|
|
{
|
|
if (!string.IsNullOrEmpty(description))
|
|
{
|
|
return json.Replace("\"description\": \"\"", $"\"description\": \"{description}\"");
|
|
}
|
|
return json;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the toolbox record response JSON.
|
|
/// </summary>
|
|
public static string GetToolboxRecordResponseJson() => s_toolboxRecordResponseJson;
|
|
|
|
/// <summary>
|
|
/// Gets the toolbox version response JSON.
|
|
/// </summary>
|
|
public static string GetToolboxVersionResponseJson() => s_toolboxVersionResponseJson;
|
|
|
|
/// <summary>
|
|
/// Gets the toolbox version response JSON with decoration fields on tools.
|
|
/// </summary>
|
|
public static string GetToolboxVersionWithDecorationFieldsJson() => s_toolboxVersionWithDecorationFieldsJson;
|
|
}
|