From d0403cb78c7d7deeee9f32765a5fdefb6cb79754 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:25:27 +0000 Subject: [PATCH 1/4] Initial plan From 7d71db943064f49f5bc1a35f2e18a312698b1a56 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:30:43 +0000 Subject: [PATCH 2/4] fix: SendAndWaitAsync throws OperationCanceledException when token is cancelled Co-authored-by: SteveSandersonMS <1101362+SteveSandersonMS@users.noreply.github.com> --- dotnet/src/Session.cs | 8 +++++++- dotnet/test/SessionTests.cs | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 4feeb9f9..45f093b1 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -147,6 +147,7 @@ public async Task SendAsync(MessageOptions options, CancellationToken ca /// A that can be used to cancel the operation. /// A task that resolves with the final assistant message event, or null if none was received. /// Thrown if the timeout is reached before the session becomes idle. + /// Thrown if the is cancelled. /// Thrown if the session has been disposed. /// /// @@ -201,7 +202,12 @@ void Handler(SessionEvent evt) cts.CancelAfter(effectiveTimeout); using var registration = cts.Token.Register(() => - tcs.TrySetException(new TimeoutException($"SendAndWaitAsync timed out after {effectiveTimeout}"))); + { + if (cancellationToken.IsCancellationRequested) + tcs.TrySetCanceled(cancellationToken); + else + tcs.TrySetException(new TimeoutException($"SendAndWaitAsync timed out after {effectiveTimeout}")); + }); return await tcs.Task; } diff --git a/dotnet/test/SessionTests.cs b/dotnet/test/SessionTests.cs index c9a152ce..6b1a83b1 100644 --- a/dotnet/test/SessionTests.cs +++ b/dotnet/test/SessionTests.cs @@ -403,6 +403,23 @@ public async Task SendAndWait_Throws_On_Timeout() Assert.Contains("timed out", ex.Message); } + [Fact] + public async Task SendAndWait_Throws_OperationCanceledException_When_Token_Cancelled() + { + var session = await Client.CreateSessionAsync(); + + using var cts = new CancellationTokenSource(); + + // Cancel before any response can arrive + var sendTask = session.SendAndWaitAsync( + new MessageOptions { Prompt = "Run 'sleep 2 && echo done'" }, + cancellationToken: cts.Token); + + cts.Cancel(); + + await Assert.ThrowsAsync(() => sendTask); + } + [Fact] public async Task Should_Create_Session_With_Custom_Config_Dir() { From e2569eb2ccc856f0e3ad53e93160031894c2540f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:51:30 +0000 Subject: [PATCH 3/4] fix: improve cancellation test to wait for tool execution before cancelling Co-authored-by: SteveSandersonMS <1101362+SteveSandersonMS@users.noreply.github.com> --- dotnet/test/SessionTests.cs | 13 +++++++--- ...anceledexception_when_token_cancelled.yaml | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml diff --git a/dotnet/test/SessionTests.cs b/dotnet/test/SessionTests.cs index 6b1a83b1..7b7dcafd 100644 --- a/dotnet/test/SessionTests.cs +++ b/dotnet/test/SessionTests.cs @@ -408,16 +408,23 @@ public async Task SendAndWait_Throws_OperationCanceledException_When_Token_Cance { var session = await Client.CreateSessionAsync(); + // Set up wait for tool execution to start BEFORE sending + var toolStartTask = TestHelper.GetNextEventOfTypeAsync(session); + using var cts = new CancellationTokenSource(); - // Cancel before any response can arrive + // Start SendAndWaitAsync - don't await it yet var sendTask = session.SendAndWaitAsync( - new MessageOptions { Prompt = "Run 'sleep 2 && echo done'" }, + new MessageOptions { Prompt = "run the shell command 'sleep 10' (note this works on both bash and PowerShell)" }, cancellationToken: cts.Token); + // Wait for the tool to begin executing before cancelling + await toolStartTask; + + // Cancel the token cts.Cancel(); - await Assert.ThrowsAsync(() => sendTask); + await Assert.ThrowsAnyAsync(() => sendTask); } [Fact] diff --git a/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml b/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml new file mode 100644 index 00000000..04766065 --- /dev/null +++ b/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml @@ -0,0 +1,24 @@ +models: + - claude-sonnet-4.5 +conversations: + - messages: + - role: system + content: ${system} + - role: user + content: run the shell command 'sleep 10' (note this works on both bash and PowerShell) + - role: assistant + content: I'll run the sleep command for 10 seconds. + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running sleep command"}' + - role: assistant + tool_calls: + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"sleep 10","description":"Run sleep 10 command","mode":"sync","initial_wait":15}' From eeac5fdfd90cbfd8a7abc84bb23c04e016023aa0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:00:05 +0000 Subject: [PATCH 4/4] test: replace manually-written snapshot YAML with auto-generated one Co-authored-by: SteveSandersonMS <1101362+SteveSandersonMS@users.noreply.github.com> --- ...hrows_operationcanceledexception_when_token_cancelled.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml b/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml index 04766065..a03140fa 100644 --- a/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml +++ b/test/snapshots/session/sendandwait_throws_operationcanceledexception_when_token_cancelled.yaml @@ -7,7 +7,7 @@ conversations: - role: user content: run the shell command 'sleep 10' (note this works on both bash and PowerShell) - role: assistant - content: I'll run the sleep command for 10 seconds. + content: I'll run the sleep command for you. - role: assistant tool_calls: - id: toolcall_0 @@ -21,4 +21,4 @@ conversations: type: function function: name: ${shell} - arguments: '{"command":"sleep 10","description":"Run sleep 10 command","mode":"sync","initial_wait":15}' + arguments: '{"command":"sleep 10","description":"Execute sleep 10 command","initial_wait":15,"mode":"sync"}'