Skip to content

Commit 0c67dbb

Browse files
.NET: Update GitHub.Copilot.SDK to 0.1.23 and copy new session config prope… (#3788)
* Update GitHub.Copilot.SDK to 0.1.23 and copy new session config properties - Bump GitHub.Copilot.SDK from 0.1.18 to 0.1.23 - Add new SessionConfig properties: ReasoningEffort, Hooks, OnUserInputRequest, WorkingDirectory, ConfigDir, InfiniteSessions - Add missing ResumeSessionConfig properties: Model, SystemMessage, AvailableTools, ExcludedTools, ReasoningEffort, Hooks, OnUserInputRequest, WorkingDirectory, ConfigDir, InfiniteSessions - Fix UserMessageDataAttachmentsItem -> UserMessageDataAttachmentsItemFile for new polymorphic attachment API - Add unit tests for new session config properties * Address PR review: centralize config mapping and improve test coverage - Extract CopySessionConfig/CopyResumeSessionConfig as internal static helpers to eliminate duplicated mapping logic between RunCoreStreamingAsync and CreateResumeConfig (addresses reviewer comment on drift risk) - Add InternalsVisibleTo for unit test project - Replace shallow constructor tests with comprehensive property-verification tests that validate every config property is correctly copied, including OnUserInputRequest (addresses reviewer comments on test coverage) * Remove accidentally committed git-lfs hooks
1 parent a2856d3 commit 0c67dbb

4 files changed

Lines changed: 183 additions & 25 deletions

File tree

dotnet/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<PackageVersion Include="Microsoft.SemanticKernel.Agents.AzureAI" Version="1.67.0-preview" />
9090
<PackageVersion Include="Microsoft.SemanticKernel.Plugins.OpenApi" Version="1.67.0" />
9191
<!-- Agent SDKs -->
92-
<PackageVersion Include="GitHub.Copilot.SDK" Version="0.1.18" />
92+
<PackageVersion Include="GitHub.Copilot.SDK" Version="0.1.23" />
9393
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.3.171-beta" />
9494
<!-- M365 Agents SDK -->
9595
<PackageVersion Include="AdaptiveCards" Version="3.1.0" />

dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/GitHubCopilotAgent.cs

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -147,21 +147,7 @@ protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingA
147147

148148
// Create or resume a session with streaming enabled
149149
SessionConfig sessionConfig = this._sessionConfig != null
150-
? new SessionConfig
151-
{
152-
Model = this._sessionConfig.Model,
153-
Tools = this._sessionConfig.Tools,
154-
SystemMessage = this._sessionConfig.SystemMessage,
155-
AvailableTools = this._sessionConfig.AvailableTools,
156-
ExcludedTools = this._sessionConfig.ExcludedTools,
157-
Provider = this._sessionConfig.Provider,
158-
OnPermissionRequest = this._sessionConfig.OnPermissionRequest,
159-
McpServers = this._sessionConfig.McpServers,
160-
CustomAgents = this._sessionConfig.CustomAgents,
161-
SkillDirectories = this._sessionConfig.SkillDirectories,
162-
DisabledSkills = this._sessionConfig.DisabledSkills,
163-
Streaming = true
164-
}
150+
? CopySessionConfig(this._sessionConfig)
165151
: new SessionConfig { Streaming = true };
166152

167153
CopilotSession copilotSession;
@@ -283,16 +269,64 @@ private async Task EnsureClientStartedAsync(CancellationToken cancellationToken)
283269
}
284270

285271
private ResumeSessionConfig CreateResumeConfig()
272+
{
273+
return CopyResumeSessionConfig(this._sessionConfig);
274+
}
275+
276+
/// <summary>
277+
/// Copies all supported properties from a source <see cref="SessionConfig"/> into a new instance
278+
/// with <see cref="SessionConfig.Streaming"/> set to <c>true</c>.
279+
/// </summary>
280+
internal static SessionConfig CopySessionConfig(SessionConfig source)
281+
{
282+
return new SessionConfig
283+
{
284+
Model = source.Model,
285+
ReasoningEffort = source.ReasoningEffort,
286+
Tools = source.Tools,
287+
SystemMessage = source.SystemMessage,
288+
AvailableTools = source.AvailableTools,
289+
ExcludedTools = source.ExcludedTools,
290+
Provider = source.Provider,
291+
OnPermissionRequest = source.OnPermissionRequest,
292+
OnUserInputRequest = source.OnUserInputRequest,
293+
Hooks = source.Hooks,
294+
WorkingDirectory = source.WorkingDirectory,
295+
ConfigDir = source.ConfigDir,
296+
McpServers = source.McpServers,
297+
CustomAgents = source.CustomAgents,
298+
SkillDirectories = source.SkillDirectories,
299+
DisabledSkills = source.DisabledSkills,
300+
InfiniteSessions = source.InfiniteSessions,
301+
Streaming = true
302+
};
303+
}
304+
305+
/// <summary>
306+
/// Copies all supported properties from a source <see cref="SessionConfig"/> into a new
307+
/// <see cref="ResumeSessionConfig"/> with <see cref="ResumeSessionConfig.Streaming"/> set to <c>true</c>.
308+
/// </summary>
309+
internal static ResumeSessionConfig CopyResumeSessionConfig(SessionConfig? source)
286310
{
287311
return new ResumeSessionConfig
288312
{
289-
Tools = this._sessionConfig?.Tools,
290-
Provider = this._sessionConfig?.Provider,
291-
OnPermissionRequest = this._sessionConfig?.OnPermissionRequest,
292-
McpServers = this._sessionConfig?.McpServers,
293-
CustomAgents = this._sessionConfig?.CustomAgents,
294-
SkillDirectories = this._sessionConfig?.SkillDirectories,
295-
DisabledSkills = this._sessionConfig?.DisabledSkills,
313+
Model = source?.Model,
314+
ReasoningEffort = source?.ReasoningEffort,
315+
Tools = source?.Tools,
316+
SystemMessage = source?.SystemMessage,
317+
AvailableTools = source?.AvailableTools,
318+
ExcludedTools = source?.ExcludedTools,
319+
Provider = source?.Provider,
320+
OnPermissionRequest = source?.OnPermissionRequest,
321+
OnUserInputRequest = source?.OnUserInputRequest,
322+
Hooks = source?.Hooks,
323+
WorkingDirectory = source?.WorkingDirectory,
324+
ConfigDir = source?.ConfigDir,
325+
McpServers = source?.McpServers,
326+
CustomAgents = source?.CustomAgents,
327+
SkillDirectories = source?.SkillDirectories,
328+
DisabledSkills = source?.DisabledSkills,
329+
InfiniteSessions = source?.InfiniteSessions,
296330
Streaming = true
297331
};
298332
}
@@ -427,9 +461,8 @@ private AgentResponseUpdate ConvertToAgentResponseUpdate(SessionEvent sessionEve
427461
string tempFilePath = await dataContent.SaveToAsync(tempDir, cancellationToken).ConfigureAwait(false);
428462

429463
attachments ??= [];
430-
attachments.Add(new UserMessageDataAttachmentsItem
464+
attachments.Add(new UserMessageDataAttachmentsItemFile
431465
{
432-
Type = UserMessageDataAttachmentsItemType.File,
433466
Path = tempFilePath,
434467
DisplayName = Path.GetFileName(tempFilePath)
435468
});

dotnet/src/Microsoft.Agents.AI.GitHub.Copilot/Microsoft.Agents.AI.GitHub.Copilot.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
<ProjectReference Include="..\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
1818
</ItemGroup>
1919

20+
<ItemGroup>
21+
<InternalsVisibleTo Include="Microsoft.Agents.AI.GitHub.Copilot.UnitTests" />
22+
</ItemGroup>
23+
2024
<ItemGroup>
2125
<PackageReference Include="GitHub.Copilot.SDK" />
2226
</ItemGroup>

dotnet/tests/Microsoft.Agents.AI.GitHub.Copilot.UnitTests/GitHubCopilotAgentTests.cs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,125 @@ public void Constructor_WithTools_InitializesCorrectly()
100100
Assert.NotNull(agent);
101101
Assert.NotNull(agent.Id);
102102
}
103+
104+
[Fact]
105+
public void CopySessionConfig_CopiesAllProperties()
106+
{
107+
// Arrange
108+
List<AIFunction> tools = [AIFunctionFactory.Create(() => "test", "TestFunc", "Test function")];
109+
var hooks = new SessionHooks();
110+
var infiniteSessions = new InfiniteSessionConfig();
111+
var systemMessage = new SystemMessageConfig { Mode = SystemMessageMode.Append, Content = "Be helpful" };
112+
PermissionHandler permissionHandler = (_, _) => Task.FromResult(new PermissionRequestResult());
113+
UserInputHandler userInputHandler = (_, _) => Task.FromResult(new UserInputResponse { Answer = "input" });
114+
var mcpServers = new Dictionary<string, object> { ["server1"] = new McpLocalServerConfig() };
115+
116+
var source = new SessionConfig
117+
{
118+
Model = "gpt-4o",
119+
ReasoningEffort = "high",
120+
Tools = tools,
121+
SystemMessage = systemMessage,
122+
AvailableTools = ["tool1", "tool2"],
123+
ExcludedTools = ["tool3"],
124+
WorkingDirectory = "/workspace",
125+
ConfigDir = "/config",
126+
Hooks = hooks,
127+
InfiniteSessions = infiniteSessions,
128+
OnPermissionRequest = permissionHandler,
129+
OnUserInputRequest = userInputHandler,
130+
McpServers = mcpServers,
131+
DisabledSkills = ["skill1"],
132+
};
133+
134+
// Act
135+
SessionConfig result = GitHubCopilotAgent.CopySessionConfig(source);
136+
137+
// Assert
138+
Assert.Equal("gpt-4o", result.Model);
139+
Assert.Equal("high", result.ReasoningEffort);
140+
Assert.Same(tools, result.Tools);
141+
Assert.Same(systemMessage, result.SystemMessage);
142+
Assert.Equal(new List<string> { "tool1", "tool2" }, result.AvailableTools);
143+
Assert.Equal(new List<string> { "tool3" }, result.ExcludedTools);
144+
Assert.Equal("/workspace", result.WorkingDirectory);
145+
Assert.Equal("/config", result.ConfigDir);
146+
Assert.Same(hooks, result.Hooks);
147+
Assert.Same(infiniteSessions, result.InfiniteSessions);
148+
Assert.Same(permissionHandler, result.OnPermissionRequest);
149+
Assert.Same(userInputHandler, result.OnUserInputRequest);
150+
Assert.Same(mcpServers, result.McpServers);
151+
Assert.Equal(new List<string> { "skill1" }, result.DisabledSkills);
152+
Assert.True(result.Streaming);
153+
}
154+
155+
[Fact]
156+
public void CopyResumeSessionConfig_CopiesAllProperties()
157+
{
158+
// Arrange
159+
List<AIFunction> tools = [AIFunctionFactory.Create(() => "test", "TestFunc", "Test function")];
160+
var hooks = new SessionHooks();
161+
var infiniteSessions = new InfiniteSessionConfig();
162+
var systemMessage = new SystemMessageConfig { Mode = SystemMessageMode.Append, Content = "Be helpful" };
163+
PermissionHandler permissionHandler = (_, _) => Task.FromResult(new PermissionRequestResult());
164+
UserInputHandler userInputHandler = (_, _) => Task.FromResult(new UserInputResponse { Answer = "input" });
165+
var mcpServers = new Dictionary<string, object> { ["server1"] = new McpLocalServerConfig() };
166+
167+
var source = new SessionConfig
168+
{
169+
Model = "gpt-4o",
170+
ReasoningEffort = "high",
171+
Tools = tools,
172+
SystemMessage = systemMessage,
173+
AvailableTools = ["tool1", "tool2"],
174+
ExcludedTools = ["tool3"],
175+
WorkingDirectory = "/workspace",
176+
ConfigDir = "/config",
177+
Hooks = hooks,
178+
InfiniteSessions = infiniteSessions,
179+
OnPermissionRequest = permissionHandler,
180+
OnUserInputRequest = userInputHandler,
181+
McpServers = mcpServers,
182+
DisabledSkills = ["skill1"],
183+
};
184+
185+
// Act
186+
ResumeSessionConfig result = GitHubCopilotAgent.CopyResumeSessionConfig(source);
187+
188+
// Assert
189+
Assert.Equal("gpt-4o", result.Model);
190+
Assert.Equal("high", result.ReasoningEffort);
191+
Assert.Same(tools, result.Tools);
192+
Assert.Same(systemMessage, result.SystemMessage);
193+
Assert.Equal(new List<string> { "tool1", "tool2" }, result.AvailableTools);
194+
Assert.Equal(new List<string> { "tool3" }, result.ExcludedTools);
195+
Assert.Equal("/workspace", result.WorkingDirectory);
196+
Assert.Equal("/config", result.ConfigDir);
197+
Assert.Same(hooks, result.Hooks);
198+
Assert.Same(infiniteSessions, result.InfiniteSessions);
199+
Assert.Same(permissionHandler, result.OnPermissionRequest);
200+
Assert.Same(userInputHandler, result.OnUserInputRequest);
201+
Assert.Same(mcpServers, result.McpServers);
202+
Assert.Equal(new List<string> { "skill1" }, result.DisabledSkills);
203+
Assert.True(result.Streaming);
204+
}
205+
206+
[Fact]
207+
public void CopyResumeSessionConfig_WithNullSource_ReturnsDefaults()
208+
{
209+
// Act
210+
ResumeSessionConfig result = GitHubCopilotAgent.CopyResumeSessionConfig(null);
211+
212+
// Assert
213+
Assert.Null(result.Model);
214+
Assert.Null(result.ReasoningEffort);
215+
Assert.Null(result.Tools);
216+
Assert.Null(result.SystemMessage);
217+
Assert.Null(result.OnPermissionRequest);
218+
Assert.Null(result.OnUserInputRequest);
219+
Assert.Null(result.Hooks);
220+
Assert.Null(result.WorkingDirectory);
221+
Assert.Null(result.ConfigDir);
222+
Assert.True(result.Streaming);
223+
}
103224
}

0 commit comments

Comments
 (0)