Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dotnet/src/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2276,7 +2276,7 @@ internal record CreateSessionRequest(
string? ClientName,
string? ReasoningEffort,
ReasoningSummary? ReasoningSummary,
string? ContextTier,
ContextTier? ContextTier,
IList<ToolDefinition>? Tools,
SystemMessageConfig? SystemMessage,
IList<string>? AvailableTools,
Expand Down Expand Up @@ -2362,7 +2362,7 @@ internal record ResumeSessionRequest(
string? Model,
string? ReasoningEffort,
ReasoningSummary? ReasoningSummary,
string? ContextTier,
ContextTier? ContextTier,
IList<ToolDefinition>? Tools,
SystemMessageConfig? SystemMessage,
IList<string>? AvailableTools,
Expand Down
64 changes: 62 additions & 2 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2390,6 +2390,65 @@ public sealed class CloudSessionOptions
public CloudSessionRepository? Repository { get; set; }
}

/// <summary>
/// Context window tier for models that support tiered context windows.
/// </summary>
[JsonConverter(typeof(ContextTier.Converter))]
[DebuggerDisplay("{Value,nq}")]
public readonly struct ContextTier : IEquatable<ContextTier>
{
private readonly string? _value;

/// <summary>Initializes a new instance of the <see cref="ContextTier"/> struct.</summary>
/// <param name="value">The value to associate with this <see cref="ContextTier"/>.</param>
[JsonConstructor]
public ContextTier(string value)
{
ArgumentException.ThrowIfNullOrWhiteSpace(value);
_value = value;
}

/// <summary>Gets the value associated with this <see cref="ContextTier"/>.</summary>
public string Value => _value ?? string.Empty;

/// <summary>Default context tier with standard context window size.</summary>
public static ContextTier Default { get; } = new("default");

/// <summary>Extended context tier with a larger context window.</summary>
public static ContextTier LongContext { get; } = new("long_context");

/// <summary>Returns a value indicating whether two <see cref="ContextTier"/> instances are equivalent.</summary>
public static bool operator ==(ContextTier left, ContextTier right) => left.Equals(right);

/// <summary>Returns a value indicating whether two <see cref="ContextTier"/> instances are not equivalent.</summary>
public static bool operator !=(ContextTier left, ContextTier right) => !left.Equals(right);

/// <inheritdoc/>
public override bool Equals([NotNullWhen(true)] object? obj) => obj is ContextTier other && Equals(other);

/// <inheritdoc/>
public bool Equals(ContextTier other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase);

/// <inheritdoc/>
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);

/// <inheritdoc/>
public override string ToString() => Value;

/// <summary>Provides a <see cref="JsonConverter{ContextTier}"/> for serializing <see cref="ContextTier"/> instances.</summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public sealed class Converter : JsonConverter<ContextTier>
{
/// <inheritdoc/>
public override ContextTier Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
new(GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert));

/// <inheritdoc/>
public override void Write(Utf8JsonWriter writer, ContextTier value, JsonSerializerOptions options) =>
GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ContextTier));
}
}

/// <summary>
/// Shared configuration properties for creating or resuming a Copilot session.
/// Use <see cref="SessionConfig"/> when creating a new session, or
Expand Down Expand Up @@ -2497,9 +2556,10 @@ protected SessionConfigBase(SessionConfigBase? other)

/// <summary>
/// Context window tier for models that support it.
/// Valid values: "default", "long_context".
/// Use <see cref="ContextTier.Default"/> or <see cref="ContextTier.LongContext"/>
/// for the currently known tiers.
/// </summary>
public string? ContextTier { get; set; }
public ContextTier? ContextTier { get; set; }

/// <summary>Per-property overrides for model capabilities, deep-merged over runtime defaults.</summary>
public ModelCapabilitiesOverride? ModelCapabilities { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions dotnet/test/Unit/CloneTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void SessionConfig_Clone_CopiesAllProperties()
Model = "gpt-4",
ReasoningEffort = "high",
ReasoningSummary = ReasoningSummary.Detailed,
ContextTier = "long_context",
ContextTier = ContextTier.LongContext,
ConfigDirectory = "/config",
AvailableTools = ["tool1", "tool2"],
ExcludedTools = ["tool3"],
Expand Down Expand Up @@ -386,7 +386,7 @@ public void ResumeSessionConfig_Clone_CopiesContextTier()
{
var original = new ResumeSessionConfig
{
ContextTier = "long_context",
ContextTier = ContextTier.LongContext,
};

var clone = original.Clone();
Expand Down
25 changes: 25 additions & 0 deletions dotnet/test/Unit/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,31 @@ public void SessionRequests_CanSerializeReasoningSummary_WithSdkOptions()
Assert.Equal("none", resumeDocument.RootElement.GetProperty("reasoningSummary").GetString());
}

[Fact]
public void SessionRequests_CanSerializeContextTier_WithSdkOptions()
{
var options = GetSerializerOptions();
var createRequestType = GetNestedType(typeof(CopilotClient), "CreateSessionRequest");
var createRequest = CreateInternalRequest(
createRequestType,
("SessionId", "session-id"),
("ContextTier", ContextTier.LongContext));

var createJson = JsonSerializer.Serialize(createRequest, createRequestType, options);
using var createDocument = JsonDocument.Parse(createJson);
Assert.Equal("long_context", createDocument.RootElement.GetProperty("contextTier").GetString());

var resumeRequestType = GetNestedType(typeof(CopilotClient), "ResumeSessionRequest");
var resumeRequest = CreateInternalRequest(
resumeRequestType,
("SessionId", "session-id"),
("ContextTier", ContextTier.Default));

var resumeJson = JsonSerializer.Serialize(resumeRequest, resumeRequestType, options);
using var resumeDocument = JsonDocument.Parse(resumeJson);
Assert.Equal("default", resumeDocument.RootElement.GetProperty("contextTier").GetString());
}

[Fact]
public void SessionRequests_CanSerializePluginDirectoriesAndLargeOutput_WithSdkOptions()
{
Expand Down
4 changes: 2 additions & 2 deletions go/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ func TestSessionRequests_ReasoningSummary(t *testing.T) {

func TestSessionRequests_ContextTier(t *testing.T) {
t.Run("create includes contextTier in JSON when set", func(t *testing.T) {
req := createSessionRequest{ContextTier: "long_context"}
req := createSessionRequest{ContextTier: ContextTierLongContext}
data, err := json.Marshal(req)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
Expand All @@ -451,7 +451,7 @@ func TestSessionRequests_ContextTier(t *testing.T) {
})

t.Run("resume includes contextTier in JSON when set", func(t *testing.T) {
req := resumeSessionRequest{SessionID: "s1", ContextTier: "default"}
req := resumeSessionRequest{SessionID: "s1", ContextTier: ContextTierDefault}
data, err := json.Marshal(req)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
Expand Down
22 changes: 16 additions & 6 deletions go/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,16 @@ type LargeToolOutputConfig struct {
OutputDirectory string `json:"outputDir,omitempty"`
}

// ContextTier identifies a context window tier for models that support tiered context windows.
type ContextTier string

const (
// ContextTierDefault is the default context tier with standard context window size.
ContextTierDefault ContextTier = "default"
// ContextTierLongContext is the extended context tier with a larger context window.
ContextTierLongContext ContextTier = "long_context"
)

// SessionFsCapabilities declares optional provider capabilities.
type SessionFsCapabilities struct {
// Sqlite indicates whether the provider supports SQLite query/exists operations.
Expand Down Expand Up @@ -895,8 +905,8 @@ type SessionConfig struct {
// Use ReasoningSummaryNone to suppress summary output regardless of whether reasoning is enabled.
ReasoningSummary ReasoningSummary
// ContextTier pins the session to a context window tier for models that support it.
// Valid values: "default", "long_context".
ContextTier string
// Use ContextTierDefault or ContextTierLongContext for the currently known tiers.
ContextTier ContextTier
// ConfigDirectory overrides the default configuration directory location.
// When specified, the session will use this directory for storing config and state.
ConfigDirectory string
Expand Down Expand Up @@ -1298,8 +1308,8 @@ type ResumeSessionConfig struct {
// Use ReasoningSummaryNone to suppress summary output regardless of whether reasoning is enabled.
ReasoningSummary ReasoningSummary
// ContextTier pins the session to a context window tier for models that support it.
// Valid values: "default", "long_context".
ContextTier string
// Use ContextTierDefault or ContextTierLongContext for the currently known tiers.
ContextTier ContextTier
// OnPermissionRequest is an optional handler for permission requests from the server.
// When nil, permission requests are surfaced as events and left pending for the
// consumer to resolve via pending permission RPCs.
Expand Down Expand Up @@ -1660,7 +1670,7 @@ type createSessionRequest struct {
ClientName string `json:"clientName,omitempty"`
ReasoningEffort string `json:"reasoningEffort,omitempty"`
ReasoningSummary ReasoningSummary `json:"reasoningSummary,omitempty"`
ContextTier string `json:"contextTier,omitempty"`
ContextTier ContextTier `json:"contextTier,omitempty"`
Tools []Tool `json:"tools,omitempty"`
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
AvailableTools []string `json:"availableTools"`
Expand Down Expand Up @@ -1738,7 +1748,7 @@ type resumeSessionRequest struct {
Model string `json:"model,omitempty"`
ReasoningEffort string `json:"reasoningEffort,omitempty"`
ReasoningSummary ReasoningSummary `json:"reasoningSummary,omitempty"`
ContextTier string `json:"contextTier,omitempty"`
ContextTier ContextTier `json:"contextTier,omitempty"`
Tools []Tool `json:"tools,omitempty"`
SystemMessage *SystemMessageConfig `json:"systemMessage,omitempty"`
AvailableTools []string `json:"availableTools"`
Expand Down
Loading