From fed8ab8033afd8bebd64c301bf0f6e83bd450132 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Thu, 18 Jun 2026 15:57:02 -0400 Subject: [PATCH 1/2] Add .NET low-level tool-definition E2E test Related to issue #1682 but does not fix #1682. Align low_level_tool_definition coverage with PR #1721 snapshot behavior by only defining tools exercised by the shared snapshot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/SessionLifecycleE2ETests.cs | 2 +- dotnet/test/E2E/ToolsE2ETests.cs | 53 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/dotnet/test/E2E/SessionLifecycleE2ETests.cs b/dotnet/test/E2E/SessionLifecycleE2ETests.cs index 31532def2..23d2532df 100644 --- a/dotnet/test/E2E/SessionLifecycleE2ETests.cs +++ b/dotnet/test/E2E/SessionLifecycleE2ETests.cs @@ -25,7 +25,7 @@ public async Task Should_List_Created_Sessions_After_Sending_A_Message() // Sessions must have activity to be persisted to disk await session1.SendAndWaitAsync(new MessageOptions { Prompt = "Say hello" }); - await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Say world" }); + await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Say hi" }); IList? sessions = null; await TestHelper.WaitForConditionAsync( diff --git a/dotnet/test/E2E/ToolsE2ETests.cs b/dotnet/test/E2E/ToolsE2ETests.cs index 57ed6be2d..7424cfa3a 100644 --- a/dotnet/test/E2E/ToolsE2ETests.cs +++ b/dotnet/test/E2E/ToolsE2ETests.cs @@ -61,6 +61,59 @@ static string EncryptString([Description("String to encrypt")] string input) => input.ToUpperInvariant(); } + [Fact] + public async Task Low_Level_Tool_Definition() + { + string currentPhase = string.Empty; + + var session = await CreateSessionAsync(new SessionConfig + { + Tools = + [ + AIFunctionFactory.Create(SetCurrentPhase, new AIFunctionFactoryOptions + { + Name = "set_current_phase", + Description = "Sets the current phase of the agent", + }), + AIFunctionFactory.Create(SearchItems, new AIFunctionFactoryOptions + { + Name = "search_items", + Description = "Search for items by keyword", + }), + ], + AvailableTools = new ToolSet().AddCustom("*").AddBuiltIn("web_fetch"), + OnPermissionRequest = PermissionHandler.ApproveAll, + }); + + await session.SendAsync(new MessageOptions + { + Prompt = "First, set the current phase to 'analyzing'. Then search for items with keyword 'copilot'. Report the phase and search results." + }); + + var assistantMessage = await TestHelper.GetFinalAssistantMessageAsync(session); + + Assert.NotNull(assistantMessage); + var content = assistantMessage!.Data.Content ?? string.Empty; + Assert.NotEmpty(content); + Assert.Contains("analyzing", content, StringComparison.OrdinalIgnoreCase); + Assert.True(content.Contains("item_alpha", StringComparison.OrdinalIgnoreCase) + || content.Contains("item_beta", StringComparison.OrdinalIgnoreCase), + $"Expected content to mention item_alpha or item_beta, got: {content}"); + Assert.Equal("analyzing", currentPhase); + + Task SetCurrentPhase(string phase) + { + currentPhase = phase; + return Task.FromResult($"Phase set to {phase}"); + } + + Task SearchItems(AIFunctionArguments args) + { + Assert.Equal("copilot", args["keyword"]?.ToString()); + return Task.FromResult("Found: item_alpha, item_beta"); + } + } + [Fact] public async Task Handles_Tool_Calling_Errors() { From 7100ffc510652d0858aabaf6581f40b9ed345e61 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Thu, 18 Jun 2026 16:11:15 -0400 Subject: [PATCH 2/2] Fix .NET session lifecycle replay mismatch in PR 1728 Restore the second lifecycle prompt to 'Say world' to match the existing session_lifecycle snapshot and avoid replay cache misses in CI. Related to issue #1682 but does not fix #1682. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/SessionLifecycleE2ETests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/test/E2E/SessionLifecycleE2ETests.cs b/dotnet/test/E2E/SessionLifecycleE2ETests.cs index 23d2532df..31532def2 100644 --- a/dotnet/test/E2E/SessionLifecycleE2ETests.cs +++ b/dotnet/test/E2E/SessionLifecycleE2ETests.cs @@ -25,7 +25,7 @@ public async Task Should_List_Created_Sessions_After_Sending_A_Message() // Sessions must have activity to be persisted to disk await session1.SendAndWaitAsync(new MessageOptions { Prompt = "Say hello" }); - await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Say hi" }); + await session2.SendAndWaitAsync(new MessageOptions { Prompt = "Say world" }); IList? sessions = null; await TestHelper.WaitForConditionAsync(