db620d33df
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
105 lines
4.0 KiB
C#
105 lines
4.0 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Agents.AI.Hyperlight.Internal;
|
|
using Microsoft.Extensions.AI;
|
|
using Moq;
|
|
|
|
namespace Microsoft.Agents.AI.Hyperlight.UnitTests;
|
|
|
|
public sealed class ProvideAIContextTests
|
|
{
|
|
private static readonly AIAgent s_mockAgent = new Mock<AIAgent>().Object;
|
|
|
|
private static AIContextProvider.InvokingContext NewInvokingContext() => new(s_mockAgent, session: null, new AIContext());
|
|
|
|
[Fact]
|
|
public async Task ProvideAIContextAsync_ReturnsExecuteCodeToolAndInstructionsAsync()
|
|
{
|
|
// Arrange
|
|
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
|
|
|
|
// Act
|
|
var context = await provider.InvokingAsync(NewInvokingContext());
|
|
|
|
// Assert
|
|
Assert.NotNull(context);
|
|
Assert.NotNull(context!.Tools);
|
|
var tools = context.Tools!.ToList();
|
|
Assert.Single(tools);
|
|
var function = Assert.IsAssignableFrom<AIFunction>(tools[0]);
|
|
Assert.Equal("execute_code", function.Name);
|
|
Assert.False(string.IsNullOrWhiteSpace(context.Instructions));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ProvideAIContextAsync_AlwaysRequire_WrapsInApprovalRequiredAsync()
|
|
{
|
|
// Arrange
|
|
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions
|
|
{
|
|
ApprovalMode = CodeActApprovalMode.AlwaysRequire,
|
|
});
|
|
|
|
// Act
|
|
var context = await provider.InvokingAsync(NewInvokingContext());
|
|
|
|
// Assert
|
|
_ = Assert.IsType<ApprovalRequiredAIFunction>(context!.Tools!.First());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ProvideAIContextAsync_NeverRequireWithApprovalTool_WrapsInApprovalRequiredAsync()
|
|
{
|
|
// Arrange
|
|
var inner = AIFunctionFactory.Create(() => "ok", name: "t");
|
|
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions
|
|
{
|
|
ApprovalMode = CodeActApprovalMode.NeverRequire,
|
|
Tools = [new ApprovalRequiredAIFunction(inner)],
|
|
});
|
|
|
|
// Act
|
|
var context = await provider.InvokingAsync(NewInvokingContext());
|
|
|
|
// Assert
|
|
_ = Assert.IsType<ApprovalRequiredAIFunction>(context!.Tools!.First());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ProvideAIContextAsync_CapturesSnapshot_MutationsAfterDoNotAffectDescriptionAsync()
|
|
{
|
|
// Arrange
|
|
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
|
|
provider.AddTools(AIFunctionFactory.Create(() => "one", name: "first_tool"));
|
|
|
|
// Act
|
|
var context = await provider.InvokingAsync(NewInvokingContext());
|
|
provider.AddTools(AIFunctionFactory.Create(() => "two", name: "second_tool"));
|
|
|
|
// Assert — the returned execute_code description must reflect the first snapshot only.
|
|
var function = Assert.IsAssignableFrom<AIFunction>(context!.Tools!.First());
|
|
Assert.Contains("first_tool", function.Description);
|
|
Assert.DoesNotContain("second_tool", function.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ProvideAIContextAsync_AddToolsSameNameReplacement_ChangesSnapshotFingerprintAsync()
|
|
{
|
|
// Arrange
|
|
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
|
|
provider.AddTools(AIFunctionFactory.Create(() => "one", name: "same_tool"));
|
|
|
|
// Act
|
|
var firstContext = await provider.InvokingAsync(NewInvokingContext());
|
|
provider.AddTools(AIFunctionFactory.Create(() => "two", name: "same_tool"));
|
|
var secondContext = await provider.InvokingAsync(NewInvokingContext());
|
|
|
|
// Assert
|
|
var firstFunction = Assert.IsType<ExecuteCodeFunction>(firstContext!.Tools!.First());
|
|
var secondFunction = Assert.IsType<ExecuteCodeFunction>(secondContext!.Tools!.First());
|
|
Assert.NotEqual(firstFunction.ConfigFingerprint, secondFunction.ConfigFingerprint);
|
|
}
|
|
}
|