forked from github/copilot-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSessionConfigTests.cs
More file actions
115 lines (98 loc) · 4.91 KB
/
Copy pathSessionConfigTests.cs
File metadata and controls
115 lines (98 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
using System.Linq;
using System.Text.Json;
using GitHub.Copilot.SDK.Rpc;
using GitHub.Copilot.SDK.Test.Harness;
using Xunit;
using Xunit.Abstractions;
namespace GitHub.Copilot.SDK.Test;
public class SessionConfigTests(E2ETestFixture fixture, ITestOutputHelper output)
: E2ETestBase(fixture, "session_config", output)
{
private const string ViewImagePrompt = "Use the view tool to look at the file test.png and describe what you see";
private static readonly byte[] Png1X1 = Convert.FromBase64String(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==");
[Fact]
public async Task Vision_Disabled_Then_Enabled_Via_SetModel()
{
await File.WriteAllBytesAsync(Path.Join(Ctx.WorkDir, "test.png"), Png1X1);
var session = await CreateSessionAsync(new SessionConfig
{
Model = "claude-sonnet-4.5",
ModelCapabilities = new ModelCapabilitiesOverride
{
Supports = new ModelCapabilitiesOverrideSupports { Vision = false },
},
});
// Turn 1: vision off — no image_url expected
await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt });
var trafficAfterT1 = await Ctx.GetExchangesAsync();
var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList();
Assert.False(HasImageUrlContent(t1Messages), "Expected no image_url content when vision is disabled");
// Switch vision on
await session.SetModelAsync(
"claude-sonnet-4.5",
reasoningEffort: null,
modelCapabilities: new ModelCapabilitiesOverride
{
Supports = new ModelCapabilitiesOverrideSupports { Vision = true },
});
// Turn 2: vision on — image_url expected
await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt });
var trafficAfterT2 = await Ctx.GetExchangesAsync();
var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList();
Assert.NotEmpty(newExchanges);
var t2Messages = newExchanges.SelectMany(e => e.Request.Messages).ToList();
Assert.True(HasImageUrlContent(t2Messages), "Expected image_url content when vision is enabled");
await session.DisposeAsync();
}
[Fact]
public async Task Vision_Enabled_Then_Disabled_Via_SetModel()
{
await File.WriteAllBytesAsync(Path.Join(Ctx.WorkDir, "test.png"), Png1X1);
var session = await CreateSessionAsync(new SessionConfig
{
Model = "claude-sonnet-4.5",
ModelCapabilities = new ModelCapabilitiesOverride
{
Supports = new ModelCapabilitiesOverrideSupports { Vision = true },
},
});
// Turn 1: vision on — image_url expected
await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt });
var trafficAfterT1 = await Ctx.GetExchangesAsync();
var t1Messages = trafficAfterT1.SelectMany(e => e.Request.Messages).ToList();
Assert.True(HasImageUrlContent(t1Messages), "Expected image_url content when vision is enabled");
// Switch vision off
await session.SetModelAsync(
"claude-sonnet-4.5",
reasoningEffort: null,
modelCapabilities: new ModelCapabilitiesOverride
{
Supports = new ModelCapabilitiesOverrideSupports { Vision = false },
});
// Turn 2: vision off — no image_url expected in new exchanges
await session.SendAndWaitAsync(new MessageOptions { Prompt = ViewImagePrompt });
var trafficAfterT2 = await Ctx.GetExchangesAsync();
var newExchanges = trafficAfterT2.Skip(trafficAfterT1.Count).ToList();
Assert.NotEmpty(newExchanges);
var t2Messages = newExchanges.SelectMany(e => e.Request.Messages).ToList();
Assert.False(HasImageUrlContent(t2Messages), "Expected no image_url content when vision is disabled");
await session.DisposeAsync();
}
/// <summary>
/// Checks whether any user message contains an image_url content part.
/// Content can be a string (no images) or a JSON array of content parts.
/// </summary>
private static bool HasImageUrlContent(List<ChatCompletionMessage> messages)
{
return messages
.Where(m => m.Role == "user" && m.Content is { ValueKind: JsonValueKind.Array })
.Any(m => m.Content!.Value.EnumerateArray().Any(part =>
part.TryGetProperty("type", out var typeProp) &&
typeProp.ValueKind == JsonValueKind.String &&
typeProp.GetString() == "image_url"));
}
}