Skip to content

Commit a14b5f4

Browse files
syf2211SteveSandersonMS
authored andcommitted
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 a5f1174 commit a14b5f4

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
@@ -1159,6 +1159,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
11591159
config.Agent,
11601160
config.ConfigDirectory,
11611161
config.EnableConfigDiscovery,
1162+
config.CustomAgentsLocalOnly,
11621163
config.SkipEmbeddingRetrieval,
11631164
config.EmbeddingCacheStorage,
11641165
config.OrganizationCustomInstructions,
@@ -1363,6 +1364,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
13631364
config.WorkingDirectory,
13641365
config.ConfigDirectory,
13651366
config.EnableConfigDiscovery,
1367+
config.CustomAgentsLocalOnly,
13661368
config.SkipEmbeddingRetrieval,
13671369
config.EmbeddingCacheStorage,
13681370
config.OrganizationCustomInstructions,
@@ -2724,6 +2726,7 @@ internal record CreateSessionRequest(
27242726
string? Agent,
27252727
[property: JsonPropertyName("configDir")] string? ConfigDirectory,
27262728
bool? EnableConfigDiscovery,
2729+
[property: JsonPropertyName("customAgentsLocalOnly")] bool? CustomAgentsLocalOnly,
27272730
bool? SkipEmbeddingRetrieval,
27282731
EmbeddingCacheStorageMode? EmbeddingCacheStorage,
27292732
string? OrganizationCustomInstructions,
@@ -2820,6 +2823,7 @@ internal record ResumeSessionRequest(
28202823
string? WorkingDirectory,
28212824
[property: JsonPropertyName("configDir")] string? ConfigDirectory,
28222825
bool? EnableConfigDiscovery,
2826+
[property: JsonPropertyName("customAgentsLocalOnly")] bool? CustomAgentsLocalOnly,
28232827
bool? SkipEmbeddingRetrieval,
28242828
EmbeddingCacheStorageMode? EmbeddingCacheStorage,
28252829
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
@@ -593,6 +593,58 @@ public void CreateSessionRequest_CanSerializeEnableSessionTelemetry_WithSdkOptio
593593
Assert.False(root.GetProperty("enableSessionTelemetry").GetBoolean());
594594
}
595595

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

0 commit comments

Comments
 (0)