Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions dotnet/test/E2E/SessionE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,7 @@ public async Task Should_Create_A_Session_With_Appended_SystemMessage_Config()
SystemMessage = new SystemMessageConfig { Mode = SystemMessageMode.Append, Content = systemMessageSuffix }
});

await session.SendAsync(new MessageOptions { Prompt = "What is your full name?" });
var assistantMessage = await TestHelper.GetFinalAssistantMessageAsync(session);
Assert.NotNull(assistantMessage);

var content = assistantMessage!.Data.Content ?? string.Empty;
Assert.Contains("GitHub", content);
Assert.Contains("Have a nice day!", content);
await AssertAppendedSystemMessageResponseAsync(session, TimeSpan.FromSeconds(120));

var traffic = await Ctx.GetExchangesAsync();
Assert.NotEmpty(traffic);
Expand All @@ -69,6 +63,18 @@ public async Task Should_Create_A_Session_With_Appended_SystemMessage_Config()
Assert.Contains(systemMessageSuffix, systemMessage);
}

internal static async Task AssertAppendedSystemMessageResponseAsync(CopilotSession session, TimeSpan timeout)
{
// Subscribe before sending: session.idle is ephemeral and cannot be recovered from history.
var assistantMessage = await session.SendAndWaitAsync(
new MessageOptions { Prompt = "What is your full name?" }, timeout);
Assert.NotNull(assistantMessage);

var content = assistantMessage.Data.Content ?? string.Empty;
Assert.Contains("GitHub", content);
Assert.Contains("Have a nice day!", content);
}

[Fact]
public async Task Should_Create_A_Session_With_Replaced_SystemMessage_Config()
{
Expand Down
41 changes: 41 additions & 0 deletions dotnet/test/Unit/ClientSessionLifetimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,47 @@ private static void AssertMessageSource(JsonElement request, string? source)
Assert.False(request.TryGetProperty("wait", out _));
}

[Fact]
public async Task Appended_System_Message_Observes_Idle_Before_Send_Reply()
{
await using var server = await FakeCopilotServer.StartAsync();
await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });
await using var session = await client.CreateSessionAsync(new SessionConfig());
var timeout = TimeSpan.FromSeconds(5);
const string content = "I am GitHub Copilot. Have a nice day!";
var drained = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
using var subscription = session.On<SessionTitleChangedEvent>(_ => drained.TrySetResult());
server.BeforeResponseAsync = async (request, cancellationToken) =>
{
if (request.Method != "session.send")
{
return;
}

await server.SendSessionEventAsync(session.SessionId, "user.message", new()
{
["content"] = request.Params.GetProperty("prompt").GetString()
});
await server.SendSessionEventAsync(session.SessionId, "assistant.message", new()
{
["messageId"] = "appended-system-message",
["content"] = content
});
await server.SendSessionEventAsync(session.SessionId, "session.idle", new());
// Drain the idle notification before replying to session.send.
await server.SendSessionEventAsync(session.SessionId, "session.title_changed", new() { ["title"] = "fence" });
await drained.Task.WaitAsync(timeout, cancellationToken);
};

await E2E.SessionE2ETests.AssertAppendedSystemMessageResponseAsync(session, timeout);

var request = Assert.Single(server.Requests, request => request.Method == "session.send");
Assert.Equal("What is your full name?", request.Params.GetProperty("prompt").GetString());
var history = await session.GetEventsAsync();
Assert.DoesNotContain(history, evt => evt is SessionIdleEvent);
Assert.Equal(content, Assert.Single(history.OfType<AssistantMessageEvent>()).Data.Content);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
Loading