Skip to content

Commit 45ce6f9

Browse files
committed
fix(dotnet): forward CustomAgentsLocalOnly in session.create and session.resume
CustomAgentsLocalOnly was only sent via the post-create session.options.update call, which arrives after agent discovery has already completed. Mirror the Go SDK by including customAgentsLocalOnly in CreateSessionRequest and ResumeSessionRequest wire payloads. Fixes #1888
1 parent 2766820 commit 45ce6f9

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

dotnet/src/Client.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
10051005
config.Agent,
10061006
config.ConfigDirectory,
10071007
config.EnableConfigDiscovery,
1008+
config.CustomAgentsLocalOnly,
10081009
config.SkipEmbeddingRetrieval,
10091010
config.EmbeddingCacheStorage,
10101011
config.OrganizationCustomInstructions,
@@ -1205,6 +1206,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
12051206
config.WorkingDirectory,
12061207
config.ConfigDirectory,
12071208
config.EnableConfigDiscovery,
1209+
config.CustomAgentsLocalOnly,
12081210
config.SkipEmbeddingRetrieval,
12091211
config.EmbeddingCacheStorage,
12101212
config.OrganizationCustomInstructions,
@@ -2467,6 +2469,7 @@ internal record CreateSessionRequest(
24672469
string? Agent,
24682470
[property: JsonPropertyName("configDir")] string? ConfigDirectory,
24692471
bool? EnableConfigDiscovery,
2472+
[property: JsonPropertyName("customAgentsLocalOnly")] bool? CustomAgentsLocalOnly,
24702473
bool? SkipEmbeddingRetrieval,
24712474
EmbeddingCacheStorageMode? EmbeddingCacheStorage,
24722475
string? OrganizationCustomInstructions,
@@ -2557,6 +2560,7 @@ internal record ResumeSessionRequest(
25572560
string? WorkingDirectory,
25582561
[property: JsonPropertyName("configDir")] string? ConfigDirectory,
25592562
bool? EnableConfigDiscovery,
2563+
[property: JsonPropertyName("customAgentsLocalOnly")] bool? CustomAgentsLocalOnly,
25602564
bool? SkipEmbeddingRetrieval,
25612565
EmbeddingCacheStorageMode? EmbeddingCacheStorage,
25622566
string? OrganizationCustomInstructions,

dotnet/test/E2E/ClientOptionsE2ETests.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,65 @@ public async Task Should_Omit_EnableSessionTelemetry_When_Not_Set()
179179
await session.DisposeAsync();
180180
}
181181

182+
[Fact]
183+
public async Task Should_Forward_CustomAgentsLocalOnly_In_Create_Wire_Request()
184+
{
185+
var (cliPath, capturePath) = await CreateFakeCliCaptureAsync();
186+
187+
await using var client = Ctx.CreateClient(options: new CopilotClientOptions
188+
{
189+
Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]),
190+
UseLoggedInUser = false,
191+
});
192+
193+
await client.StartAsync();
194+
195+
var session = await client.CreateSessionAsync(new SessionConfig
196+
{
197+
CustomAgentsLocalOnly = true,
198+
OnPermissionRequest = PermissionHandler.ApproveAll,
199+
});
200+
201+
using var capture = JsonDocument.Parse(await File.ReadAllTextAsync(capturePath));
202+
var createRequest = GetCapturedRequestParams(capture.RootElement, "session.create");
203+
Assert.True(createRequest.GetProperty("customAgentsLocalOnly").GetBoolean());
204+
205+
await session.DisposeAsync();
206+
}
207+
208+
[Fact]
209+
public async Task Should_Forward_CustomAgentsLocalOnly_In_Resume_Wire_Request()
210+
{
211+
var (cliPath, capturePath) = await CreateFakeCliCaptureAsync();
212+
213+
await using var client = Ctx.CreateClient(options: new CopilotClientOptions
214+
{
215+
Connection = RuntimeConnection.ForStdio(path: cliPath, args: ["--capture-file", capturePath]),
216+
UseLoggedInUser = false,
217+
});
218+
219+
await client.StartAsync();
220+
221+
var createSession = await client.CreateSessionAsync(new SessionConfig
222+
{
223+
OnPermissionRequest = PermissionHandler.ApproveAll,
224+
});
225+
var sessionId = createSession.SessionId;
226+
await createSession.DisposeAsync();
227+
228+
var resumeSession = await client.ResumeSessionAsync(sessionId, new ResumeSessionConfig
229+
{
230+
CustomAgentsLocalOnly = true,
231+
OnPermissionRequest = PermissionHandler.ApproveAll,
232+
});
233+
234+
using var capture = JsonDocument.Parse(await File.ReadAllTextAsync(capturePath));
235+
var resumeRequest = GetCapturedRequestParams(capture.RootElement, "session.resume");
236+
Assert.True(resumeRequest.GetProperty("customAgentsLocalOnly").GetBoolean());
237+
238+
await resumeSession.DisposeAsync();
239+
}
240+
182241
[Fact]
183242
public async Task Should_Forward_Granular_Multitenancy_Fields_In_Create_Wire_Request()
184243
{

dotnet/test/Unit/SerializationTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,58 @@ public void CreateSessionRequest_CanSerializeEnableSessionTelemetry_WithSdkOptio
590590
Assert.False(root.GetProperty("enableSessionTelemetry").GetBoolean());
591591
}
592592

593+
[Fact]
594+
public void CreateSessionRequest_CanSerializeCustomAgentsLocalOnly_WithSdkOptions()
595+
{
596+
var options = GetSerializerOptions();
597+
var requestType = GetNestedType(typeof(CopilotClient), "CreateSessionRequest");
598+
var request = CreateInternalRequest(
599+
requestType,
600+
("SessionId", "session-id"),
601+
("CustomAgentsLocalOnly", true));
602+
603+
var json = JsonSerializer.Serialize(request, requestType, options);
604+
using var document = JsonDocument.Parse(json);
605+
Assert.True(document.RootElement.GetProperty("customAgentsLocalOnly").GetBoolean());
606+
}
607+
608+
[Fact]
609+
public void ResumeSessionRequest_CanSerializeCustomAgentsLocalOnly_WithSdkOptions()
610+
{
611+
var options = GetSerializerOptions();
612+
var requestType = GetNestedType(typeof(CopilotClient), "ResumeSessionRequest");
613+
var request = CreateInternalRequest(
614+
requestType,
615+
("SessionId", "session-id"),
616+
("CustomAgentsLocalOnly", true));
617+
618+
var json = JsonSerializer.Serialize(request, requestType, options);
619+
using var document = JsonDocument.Parse(json);
620+
Assert.True(document.RootElement.GetProperty("customAgentsLocalOnly").GetBoolean());
621+
}
622+
623+
[Fact]
624+
public void SessionRequests_OmitCustomAgentsLocalOnly_WhenUnset()
625+
{
626+
var options = GetSerializerOptions();
627+
628+
var createRequestType = GetNestedType(typeof(CopilotClient), "CreateSessionRequest");
629+
var createRequest = CreateInternalRequest(
630+
createRequestType,
631+
("SessionId", "session-id"));
632+
var createJson = JsonSerializer.Serialize(createRequest, createRequestType, options);
633+
using var createDocument = JsonDocument.Parse(createJson);
634+
Assert.False(createDocument.RootElement.TryGetProperty("customAgentsLocalOnly", out _));
635+
636+
var resumeRequestType = GetNestedType(typeof(CopilotClient), "ResumeSessionRequest");
637+
var resumeRequest = CreateInternalRequest(
638+
resumeRequestType,
639+
("SessionId", "session-id"));
640+
var resumeJson = JsonSerializer.Serialize(resumeRequest, resumeRequestType, options);
641+
using var resumeDocument = JsonDocument.Parse(resumeJson);
642+
Assert.False(resumeDocument.RootElement.TryGetProperty("customAgentsLocalOnly", out _));
643+
}
644+
593645
[Fact]
594646
public void ResumeSessionRequest_CanSerializeEnableSessionTelemetry_WithSdkOptions()
595647
{

0 commit comments

Comments
 (0)