diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs
index feded0531..88463e73b 100644
--- a/dotnet/src/Generated/Rpc.cs
+++ b/dotnet/src/Generated/Rpc.cs
@@ -2396,7 +2396,7 @@ public sealed class ModelCapabilitiesOverride
[Experimental(Diagnostics.Experimental)]
internal sealed class ModelSwitchToRequest
{
- /// Explicit context tier for the selected model. `"default"` / `"long_context"` pin the tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier untouched.
+ /// Explicit context tier for the selected model. `"default"` / `"long_context"` apply the requested tier; omit this field to use normal model behavior with no explicit tier.
[JsonPropertyName("contextTier")]
public ContextTier? ContextTier { get; set; }
@@ -13851,7 +13851,7 @@ public async Task GetCurrentAsync(CancellationToken cancellationTo
/// Reasoning effort level to use for the model. "none" disables reasoning.
/// Reasoning summary mode to request for supported model clients.
/// Override individual model capabilities resolved by the runtime.
- /// Explicit context tier for the selected model. `"default"` / `"long_context"` pin the tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier untouched.
+ /// Explicit context tier for the selected model. `"default"` / `"long_context"` apply the requested tier; omit this field to use normal model behavior with no explicit tier.
/// The to monitor for cancellation requests. The default is .
/// The model identifier active on the session after the switch.
public async Task SwitchToAsync(string modelId, string? reasoningEffort = null, ReasoningSummary? reasoningSummary = null, ModelCapabilitiesOverride? modelCapabilities = null, ContextTier? contextTier = null, CancellationToken cancellationToken = default)
diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs
index 4140cf6e3..bd369867f 100644
--- a/dotnet/src/Session.cs
+++ b/dotnet/src/Session.cs
@@ -1576,14 +1576,40 @@ public async Task AbortAsync(CancellationToken cancellationToken = default)
///
/// await session.SetModelAsync("gpt-4.1");
/// await session.SetModelAsync("claude-sonnet-4.6", "high");
+ /// await session.SetModelAsync("gpt-4.1", new SetModelOptions { ContextTier = ContextTier.LongContext });
///
///
- public async Task SetModelAsync(string model, string? reasoningEffort, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default)
+ public Task SetModelAsync(string model, string? reasoningEffort, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default)
+ {
+ return SetModelAsync(
+ model,
+ new SetModelOptions
+ {
+ ReasoningEffort = reasoningEffort,
+ ModelCapabilities = modelCapabilities,
+ },
+ cancellationToken);
+ }
+
+ ///
+ /// Changes the model for this session.
+ /// The new model takes effect for the next message. Conversation history is preserved.
+ ///
+ /// Model ID to switch to (e.g., "gpt-4.1").
+ /// Settings for the new model.
+ /// Optional cancellation token.
+ public async Task SetModelAsync(string model, SetModelOptions options, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(model);
ThrowIfDisposed();
- await Rpc.Model.SwitchToAsync(model, reasoningEffort, reasoningSummary: null, modelCapabilities: modelCapabilities, cancellationToken: cancellationToken);
+ await Rpc.Model.SwitchToAsync(
+ model,
+ options.ReasoningEffort,
+ options.ReasoningSummary,
+ options.ModelCapabilities,
+ options.ContextTier,
+ cancellationToken);
}
///
@@ -1593,7 +1619,7 @@ public Task SetModelAsync(string model, CancellationToken cancellationToken = de
{
ThrowIfDisposed();
- return SetModelAsync(model, reasoningEffort: null, modelCapabilities: null, cancellationToken);
+ return SetModelAsync(model, new SetModelOptions(), cancellationToken);
}
///
diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs
index 99fa08c2b..7a2ad2951 100644
--- a/dotnet/src/Types.cs
+++ b/dotnet/src/Types.cs
@@ -2390,6 +2390,34 @@ public sealed class CloudSessionOptions
public CloudSessionRepository? Repository { get; set; }
}
+///
+/// Optional settings for .
+///
+public struct SetModelOptions
+{
+ ///
+ /// Reasoning effort level for the new model.
+ ///
+ public string? ReasoningEffort { get; set; }
+
+ ///
+ /// Reasoning summary mode for models that support configurable reasoning summaries.
+ ///
+ ///
+ /// Use to suppress summary output regardless of whether reasoning is enabled.
+ ///
+ public ReasoningSummary? ReasoningSummary { get; set; }
+
+ ///
+ /// Explicit context window tier for models that support it.
+ /// Leave unset to use normal model behavior with no explicit tier.
+ ///
+ public ContextTier? ContextTier { get; set; }
+
+ /// Per-property overrides for model capabilities, deep-merged over runtime defaults.
+ public ModelCapabilitiesOverride? ModelCapabilities { get; set; }
+}
+
///
/// Shared configuration properties for creating or resuming a Copilot session.
/// Use when creating a new session, or
diff --git a/go/rpc/zrpc.go b/go/rpc/zrpc.go
index af2ac3fdd..a760a715b 100644
--- a/go/rpc/zrpc.go
+++ b/go/rpc/zrpc.go
@@ -2640,9 +2640,8 @@ type ModelsListRequest struct {
// Experimental: ModelSwitchToRequest is part of an experimental API and may change or be
// removed.
type ModelSwitchToRequest struct {
- // Explicit context tier for the selected model. `"default"` / `"long_context"` pin the
- // tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier
- // untouched.
+ // Explicit context tier for the selected model. `"default"` / `"long_context"` apply the
+ // requested tier; omit this field to use normal model behavior with no explicit tier.
ContextTier *ContextTier `json:"contextTier,omitempty"`
// Override individual model capabilities resolved by the runtime
ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
diff --git a/go/session.go b/go/session.go
index 11b1a3d65..6e68631eb 100644
--- a/go/session.go
+++ b/go/session.go
@@ -1495,6 +1495,9 @@ type SetModelOptions struct {
// ReasoningSummary sets the reasoning summary mode for the new model.
// Use ReasoningSummaryNone to suppress summary output regardless of whether reasoning is enabled.
ReasoningSummary *ReasoningSummary
+ // ContextTier explicitly selects a context window tier for models that support it.
+ // Leave nil to use normal model behavior with no explicit tier.
+ ContextTier *ContextTier
// ModelCapabilities overrides individual model capabilities resolved by the runtime.
// Only non-nil fields are applied over the runtime-resolved capabilities.
ModelCapabilities *rpc.ModelCapabilitiesOverride
@@ -1516,6 +1519,7 @@ func (s *Session) SetModel(ctx context.Context, model string, opts *SetModelOpti
if opts != nil {
params.ReasoningEffort = opts.ReasoningEffort
params.ReasoningSummary = opts.ReasoningSummary
+ params.ContextTier = opts.ContextTier
params.ModelCapabilities = opts.ModelCapabilities
}
_, err := s.RPC.Model.SwitchTo(ctx, params)
diff --git a/go/session_test.go b/go/session_test.go
index 405d7bf7c..b1c36d175 100644
--- a/go/session_test.go
+++ b/go/session_test.go
@@ -1,13 +1,20 @@
package copilot
import (
+ "bufio"
+ "context"
"encoding/json"
"fmt"
+ "io"
+ "strconv"
"strings"
"sync"
"sync/atomic"
"testing"
"time"
+
+ "github.com/github/copilot-sdk/go/internal/jsonrpc2"
+ "github.com/github/copilot-sdk/go/rpc"
)
// newTestSession creates a session with an event channel and starts the consumer goroutine.
@@ -30,6 +37,136 @@ func ptr[T any](value T) *T {
return &value
}
+func TestSession_SetModelForwardsContextTier(t *testing.T) {
+ tier := ContextTierLongContext
+ params := captureSetModelRequest(t, &SetModelOptions{ContextTier: &tier})
+
+ if params["sessionId"] != "session-1" {
+ t.Fatalf("expected sessionId session-1, got %v", params["sessionId"])
+ }
+ if params["modelId"] != "gpt-4.1" {
+ t.Fatalf("expected modelId gpt-4.1, got %v", params["modelId"])
+ }
+ if params["contextTier"] != "long_context" {
+ t.Fatalf("expected contextTier long_context, got %v", params["contextTier"])
+ }
+}
+
+func TestSession_SetModelOmitsContextTierWhenUnset(t *testing.T) {
+ params := captureSetModelRequest(t, nil)
+
+ if _, ok := params["contextTier"]; ok {
+ t.Fatalf("expected contextTier to be omitted, got %v", params["contextTier"])
+ }
+}
+
+func captureSetModelRequest(t *testing.T, opts *SetModelOptions) map[string]any {
+ t.Helper()
+
+ stdinR, stdinW := io.Pipe()
+ stdoutR, stdoutW := io.Pipe()
+ defer stdinR.Close()
+ defer stdinW.Close()
+ defer stdoutR.Close()
+ defer stdoutW.Close()
+
+ client := jsonrpc2.NewClient(stdinW, stdoutR)
+ client.Start()
+ defer client.Stop()
+
+ paramsCh := make(chan map[string]any, 1)
+ errCh := make(chan error, 1)
+
+ go func() {
+ frame, err := readTestJSONRPCFrame(stdinR)
+ if err != nil {
+ errCh <- err
+ return
+ }
+
+ var request struct {
+ ID json.RawMessage `json:"id"`
+ Method string `json:"method"`
+ Params map[string]any `json:"params"`
+ }
+ if err := json.Unmarshal(frame, &request); err != nil {
+ errCh <- err
+ return
+ }
+ if request.Method != "session.model.switchTo" {
+ errCh <- fmt.Errorf("expected session.model.switchTo, got %s", request.Method)
+ return
+ }
+
+ paramsCh <- request.Params
+
+ response := map[string]any{
+ "jsonrpc": "2.0",
+ "id": json.RawMessage(request.ID),
+ "result": map[string]any{},
+ }
+ data, err := json.Marshal(response)
+ if err != nil {
+ errCh <- err
+ return
+ }
+ if _, err := fmt.Fprintf(stdoutW, "Content-Length: %d\r\n\r\n%s", len(data), data); err != nil {
+ errCh <- err
+ return
+ }
+ }()
+
+ session := &Session{
+ SessionID: "session-1",
+ client: client,
+ RPC: rpc.NewSessionRpc(client, "session-1"),
+ }
+ if err := session.SetModel(context.Background(), "gpt-4.1", opts); err != nil {
+ t.Fatalf("SetModel failed: %v", err)
+ }
+
+ select {
+ case params := <-paramsCh:
+ return params
+ case err := <-errCh:
+ t.Fatal(err)
+ case <-time.After(2 * time.Second):
+ t.Fatal("timed out waiting for session.model.switchTo request")
+ }
+ return nil
+}
+
+func readTestJSONRPCFrame(r io.Reader) ([]byte, error) {
+ reader := bufio.NewReader(r)
+ var contentLength int
+ for {
+ line, err := reader.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ line = strings.TrimSpace(line)
+ if line == "" {
+ break
+ }
+ name, value, ok := strings.Cut(line, ":")
+ if !ok {
+ return nil, fmt.Errorf("invalid header line %q", line)
+ }
+ if name == "Content-Length" {
+ contentLength, err = strconv.Atoi(strings.TrimSpace(value))
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ if contentLength == 0 {
+ return nil, fmt.Errorf("missing Content-Length header")
+ }
+ data := make([]byte, contentLength)
+ _, err := io.ReadFull(reader, data)
+ return data, err
+}
+
func TestSession_On(t *testing.T) {
t.Run("multiple handlers all receive events", func(t *testing.T) {
session, cleanup := newTestSession()
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index b18907204..46a3088b4 100644
--- a/nodejs/package-lock.json
+++ b/nodejs/package-lock.json
@@ -9,7 +9,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.57-3",
+ "@github/copilot": "^1.0.57-4",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -663,9 +663,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.57-3.tgz",
- "integrity": "sha512-Yo0ebyTybaoZI1TsCOxlzwEn6jxHR2eiiZkTXLMtj2wnXj/TZZWUGCWQo/LltvFPjOjLbe0TR6pzmzKNr3v0VA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.57-4.tgz",
+ "integrity": "sha512-EkMOKTbxPEMa8L3Q/Heex+Q3qIWh0sqY6998weX3QeeVG8X9lzZw+XH8yN/ITBjrP9jcPwW+isbLU18l9m7s7A==",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"detect-libc": "^2.1.2"
@@ -674,20 +674,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.57-3",
- "@github/copilot-darwin-x64": "1.0.57-3",
- "@github/copilot-linux-arm64": "1.0.57-3",
- "@github/copilot-linux-x64": "1.0.57-3",
- "@github/copilot-linuxmusl-arm64": "1.0.57-3",
- "@github/copilot-linuxmusl-x64": "1.0.57-3",
- "@github/copilot-win32-arm64": "1.0.57-3",
- "@github/copilot-win32-x64": "1.0.57-3"
+ "@github/copilot-darwin-arm64": "1.0.57-4",
+ "@github/copilot-darwin-x64": "1.0.57-4",
+ "@github/copilot-linux-arm64": "1.0.57-4",
+ "@github/copilot-linux-x64": "1.0.57-4",
+ "@github/copilot-linuxmusl-arm64": "1.0.57-4",
+ "@github/copilot-linuxmusl-x64": "1.0.57-4",
+ "@github/copilot-win32-arm64": "1.0.57-4",
+ "@github/copilot-win32-x64": "1.0.57-4"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.57-3.tgz",
- "integrity": "sha512-1i0D7EByvaIl71aT60jWE/Rd7chdrcs7uETRp9ZO0dmW74ScWC0fF7qywFfiYY81PCeuHJoKfq0iMcuwt3fb5w==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-NI5FOzEPuvUONclGW818PToyG9EeBeb33E0OzLsCL8649uJketMzr9gjHWAHbF5C67bRF/xZ/DxvrhrEYunWKw==",
"cpu": [
"arm64"
],
@@ -701,9 +701,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.57-3.tgz",
- "integrity": "sha512-s7EuHBRMhaOX+BPR3ys+3OgndNy53csI688Nsi52GiKypx1Ma287ESHEvK9IWZCqtzq3ApxsEdyX8q7enhGstg==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.57-4.tgz",
+ "integrity": "sha512-wvpTb0SLF3wxGOxtUDBLZgePkVxkuw3Bu3nMuazemeKVx03hsGjvvYz8rwAqEEnkonElx3PlADu5eaC6QO//zg==",
"cpu": [
"x64"
],
@@ -717,9 +717,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.57-3.tgz",
- "integrity": "sha512-b/061/sNsj/DVO8cHor75H9iV7rMXHPFdeJhL4grn8TU1ooIpGDCmBafWIYcE6oJGJX88ryLVWOraRS63KSSaA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-4RCCM0PGssfUCZAKxIBLaNXEelW6lw9px0GwCuz7XGvFEYmZmGyC4ArqlrM51alZWnR7MRoaxbRdRmEV2AVdqQ==",
"cpu": [
"arm64"
],
@@ -733,9 +733,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.57-3.tgz",
- "integrity": "sha512-E1faDFGzdlCw3FSh5JlBfBxHQhp9YGk9Qx+a0ZXtTZxQ3WiPoy8DfTaoc6HlT1sZo8dGPvfmJfmCHg52jhmfyA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.57-4.tgz",
+ "integrity": "sha512-BZhp1lYZb/Y/GEb42OdblEHasHdnmwm7Qg7BeR797w34/m7/0m9k//kqggEU1qdVPTvii4SXjdYoelf7CphjRw==",
"cpu": [
"x64"
],
@@ -749,9 +749,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.57-3.tgz",
- "integrity": "sha512-cAOSAtlPXZuJv+zuVkt/YXIwbSoi5aYppxfau3tYDPpiTO/9YAwQYWqXz+GWuqWe3hegzXe6bCeyGDsunhqRtg==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-jZ/RpgbYODgvyDzhgUYBNZzMy8r3MRso2Z8THpRCEYVawScQ7+DM9WWe/2+R8WZ0ipDa+omfm+dFSOPCYSVVug==",
"cpu": [
"arm64"
],
@@ -765,9 +765,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.57-3.tgz",
- "integrity": "sha512-jLmUpc8jAT5LH6SQncbyjTEU/bcsM7JrGKUfhV0PeJAU5Z7sOuZekeeVxA/Lq4yI+aBod9cE8kFjB3+KXYK0DQ==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.57-4.tgz",
+ "integrity": "sha512-PXcMGlk9wTPIFAmzfFQreM5azF1V6k4lD4fb2ySg5iYcmtCLV+HG2FlcVwZnJUrNa0da46pmROjzJXT4QPV5Yw==",
"cpu": [
"x64"
],
@@ -781,9 +781,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.57-3.tgz",
- "integrity": "sha512-RRP9+EUdcKz7X12n3Z78hwFTLwCqVi7RML/Mfr30cCvKk0ypMS3Nnlo780exMj2Ba1Da2RHv08DvMvUttqBbFA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-ChvV8EDHUkiKcCXdrJQksbLrOMcVnl0xerRRMHNHFMGReBfK8+/TyiKgEhw/R3qRI5NnBv7QvBDRhp0KHZ7rqQ==",
"cpu": [
"arm64"
],
@@ -797,9 +797,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.57-3.tgz",
- "integrity": "sha512-SYvCUrtIJzhHuz2XKGDpY5mmCVbaUjF64ZtG/m2zBKsnO9j/Aa9aXw9p3LAk6bbKlXIrHFadE6PTsi0YbOmT9w==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.57-4.tgz",
+ "integrity": "sha512-xMWYYUL+5HaYy+ddoL6IHVkvLyk2TauXvYUl7b73vqp0elRF2SwEZLFWfYts3L2+wcEkCnYWeOO7lSnT24+FuQ==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index a88fc9021..fb9a591a6 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.57-3",
+ "@github/copilot": "^1.0.57-4",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index 44e290a09..c427cd47b 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,7 +18,7 @@
"version": "0.0.0-dev",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.57-3",
+ "@github/copilot": "^1.0.57-4",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 7e9a86da8..9c6ea74df 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -4961,10 +4961,7 @@ export interface ModelSwitchToRequest {
reasoningEffort?: string;
reasoningSummary?: ReasoningSummary;
modelCapabilities?: ModelCapabilitiesOverride;
- /**
- * Explicit context tier for the selected model. `"default"` / `"long_context"` pin the tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier untouched.
- */
- contextTier?: ContextTier | null;
+ contextTier?: ContextTier;
}
/**
* The model identifier active on the session after the switch.
diff --git a/nodejs/src/session.ts b/nodejs/src/session.ts
index b7b9c217a..854a1a0d4 100644
--- a/nodejs/src/session.ts
+++ b/nodejs/src/session.ts
@@ -30,6 +30,7 @@ import type {
MessageOptions,
PermissionHandler,
PermissionRequest,
+ ContextTier,
ReasoningEffort,
ReasoningSummary,
ModelCapabilitiesOverride,
@@ -1210,6 +1211,7 @@ export class CopilotSession {
options?: {
reasoningEffort?: ReasoningEffort;
reasoningSummary?: ReasoningSummary;
+ contextTier?: ContextTier;
modelCapabilities?: ModelCapabilitiesOverride;
}
): Promise {
diff --git a/nodejs/test/client.test.ts b/nodejs/test/client.test.ts
index 3a1e83460..657ec7c9c 100644
--- a/nodejs/test/client.test.ts
+++ b/nodejs/test/client.test.ts
@@ -1004,6 +1004,7 @@ describe("CopilotClient", () => {
await session.setModel("claude-sonnet-4.6", {
reasoningEffort: "high",
reasoningSummary: "detailed",
+ contextTier: "long_context",
});
expect(spy).toHaveBeenCalledWith("session.model.switchTo", {
@@ -1011,6 +1012,7 @@ describe("CopilotClient", () => {
modelId: "claude-sonnet-4.6",
reasoningEffort: "high",
reasoningSummary: "detailed",
+ contextTier: "long_context",
});
spy.mockRestore();
diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py
index 2969d7b6c..12bff9e7f 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -15460,9 +15460,8 @@ class ModelSwitchToRequest:
"""Model identifier to switch to"""
context_tier: ContextTier | None = None
- """Explicit context tier for the selected model. `"default"` / `"long_context"` pin the
- tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier
- untouched.
+ """Explicit context tier for the selected model. `"default"` / `"long_context"` apply the
+ requested tier; omit this field to use normal model behavior with no explicit tier.
"""
model_capabilities: ModelCapabilitiesOverride | None = None
"""Override individual model capabilities resolved by the runtime"""
diff --git a/python/copilot/session.py b/python/copilot/session.py
index f9bbb24c3..7e57bd39b 100644
--- a/python/copilot/session.py
+++ b/python/copilot/session.py
@@ -55,6 +55,9 @@
UIElicitationSchemaType,
UIHandlePendingElicitationRequest,
)
+from .generated.rpc import (
+ ContextTier as _RpcContextTier,
+)
from .generated.rpc import ModelCapabilitiesOverride as _RpcModelCapabilitiesOverride
from .generated.session_events import (
AssistantMessageData,
@@ -2394,6 +2397,7 @@ async def set_model(
*,
reasoning_effort: str | None = None,
reasoning_summary: ReasoningSummary | None = None,
+ context_tier: ContextTier | None = None,
model_capabilities: ModelCapabilitiesOverride | None = None,
) -> None:
"""
@@ -2409,6 +2413,8 @@ async def set_model(
reasoning_summary: Optional reasoning summary mode for supported
models. Use "none" to suppress summary output regardless of
whether reasoning is enabled.
+ context_tier: Optional context window tier for supported models.
+ Omit to use normal model behavior with no explicit tier.
model_capabilities: Override individual model capabilities resolved by the runtime.
Raises:
@@ -2434,6 +2440,7 @@ async def set_model(
if reasoning_summary is not None
else None
),
+ context_tier=(_RpcContextTier(context_tier) if context_tier is not None else None),
model_capabilities=rpc_caps,
)
)
diff --git a/python/test_client.py b/python/test_client.py
index b1c687204..502d410ab 100644
--- a/python/test_client.py
+++ b/python/test_client.py
@@ -1132,10 +1132,15 @@ async def mock_request(method, params, **kwargs):
return await original_request(method, params, **kwargs)
client._client.request = mock_request
- await session.set_model("gpt-4.1", reasoning_summary="detailed")
+ await session.set_model(
+ "gpt-4.1",
+ reasoning_summary="detailed",
+ context_tier="long_context",
+ )
assert captured["session.model.switchTo"]["sessionId"] == session.session_id
assert captured["session.model.switchTo"]["modelId"] == "gpt-4.1"
assert captured["session.model.switchTo"]["reasoningSummary"] == "detailed"
+ assert captured["session.model.switchTo"]["contextTier"] == "long_context"
finally:
await client.force_stop()
diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs
index 2bf1ac841..d70291a79 100644
--- a/rust/src/generated/api_types.rs
+++ b/rust/src/generated/api_types.rs
@@ -4283,7 +4283,7 @@ pub struct ModelsListRequest {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ModelSwitchToRequest {
- /// Explicit context tier for the selected model. `"default"` / `"long_context"` pin the tier; `null` clears any previous explicit choice; `undefined` leaves the existing tier untouched.
+ /// Explicit context tier for the selected model. `"default"` / `"long_context"` apply the requested tier; omit this field to use normal model behavior with no explicit tier.
#[serde(skip_serializing_if = "Option::is_none")]
pub context_tier: Option,
/// Override individual model capabilities resolved by the runtime
diff --git a/rust/src/session.rs b/rust/src/session.rs
index 6a1e4f92c..6fc7a1857 100644
--- a/rust/src/session.rs
+++ b/rust/src/session.rs
@@ -524,8 +524,8 @@ impl Session {
model_id: model.to_string(),
reasoning_effort: opts.reasoning_effort,
reasoning_summary: opts.reasoning_summary,
+ context_tier: opts.context_tier,
model_capabilities: opts.model_capabilities,
- ..ModelSwitchToRequest::default()
};
self.rpc().model().switch_to(request).await?;
Ok(())
diff --git a/rust/src/types.rs b/rust/src/types.rs
index e4b9d48e2..ce01259f5 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -14,6 +14,8 @@ use serde_json::Value;
use crate::canvas::{CanvasDeclaration, CanvasHandler};
use crate::generated::api_types::OpenCanvasInstance;
+/// Context window tier for models that support tiered context windows.
+pub use crate::generated::session_events::ContextTier;
use crate::generated::session_events::ReasoningSummary;
use crate::handler::{
AutoModeSwitchHandler, ElicitationHandler, ExitPlanModeHandler, PermissionHandler,
@@ -3267,6 +3269,9 @@ pub struct SetModelOptions {
/// [`ReasoningSummary::None`] to suppress summary output regardless of
/// whether reasoning is enabled.
pub reasoning_summary: Option,
+ /// Explicit context window tier for the new model. Leave unset to use
+ /// normal model behavior with no explicit tier.
+ pub context_tier: Option,
/// Override individual model capabilities resolved by the runtime. Only
/// fields set on the override are applied; the rest fall back to the
/// runtime-resolved values for the model.
@@ -3286,6 +3291,12 @@ impl SetModelOptions {
self
}
+ /// Set [`context_tier`](Self::context_tier).
+ pub fn with_context_tier(mut self, tier: ContextTier) -> Self {
+ self.context_tier = Some(tier);
+ self
+ }
+
/// Set [`model_capabilities`](Self::model_capabilities).
pub fn with_model_capabilities(
mut self,
diff --git a/rust/tests/session_test.rs b/rust/tests/session_test.rs
index 786ba97de..7b0400bf3 100644
--- a/rust/tests/session_test.rs
+++ b/rust/tests/session_test.rs
@@ -21,7 +21,7 @@ use github_copilot_sdk::types::{
ElicitationResult, ExitPlanModeData, ExtensionInfo, MessageOptions, RequestId, SessionConfig,
SessionId, SetModelOptions, Tool, ToolInvocation, ToolResult,
};
-use github_copilot_sdk::{Client, tool};
+use github_copilot_sdk::{Client, ContextTier, tool};
use serde_json::Value;
use tokio::io::{AsyncWrite, AsyncWriteExt, duplex};
use tokio::time::timeout;
@@ -1290,7 +1290,8 @@ async fn set_model_sends_switch_to_request() {
"claude-sonnet-4",
Some(
SetModelOptions::default()
- .with_reasoning_summary(ReasoningSummary::Detailed),
+ .with_reasoning_summary(ReasoningSummary::Detailed)
+ .with_context_tier(ContextTier::LongContext),
),
)
.await
@@ -1302,6 +1303,7 @@ async fn set_model_sends_switch_to_request() {
assert_eq!(request["method"], "session.model.switchTo");
assert_eq!(request["params"]["modelId"], "claude-sonnet-4");
assert_eq!(request["params"]["reasoningSummary"], "detailed");
+ assert_eq!(request["params"]["contextTier"], "long_context");
server
.respond(
&request,
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index 34ee930ba..e011bca05 100644
--- a/test/harness/package-lock.json
+++ b/test/harness/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
- "@github/copilot": "^1.0.57-3",
+ "@github/copilot": "^1.0.57-4",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
@@ -464,9 +464,9 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.57-3.tgz",
- "integrity": "sha512-Yo0ebyTybaoZI1TsCOxlzwEn6jxHR2eiiZkTXLMtj2wnXj/TZZWUGCWQo/LltvFPjOjLbe0TR6pzmzKNr3v0VA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.57-4.tgz",
+ "integrity": "sha512-EkMOKTbxPEMa8L3Q/Heex+Q3qIWh0sqY6998weX3QeeVG8X9lzZw+XH8yN/ITBjrP9jcPwW+isbLU18l9m7s7A==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
@@ -476,20 +476,20 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.57-3",
- "@github/copilot-darwin-x64": "1.0.57-3",
- "@github/copilot-linux-arm64": "1.0.57-3",
- "@github/copilot-linux-x64": "1.0.57-3",
- "@github/copilot-linuxmusl-arm64": "1.0.57-3",
- "@github/copilot-linuxmusl-x64": "1.0.57-3",
- "@github/copilot-win32-arm64": "1.0.57-3",
- "@github/copilot-win32-x64": "1.0.57-3"
+ "@github/copilot-darwin-arm64": "1.0.57-4",
+ "@github/copilot-darwin-x64": "1.0.57-4",
+ "@github/copilot-linux-arm64": "1.0.57-4",
+ "@github/copilot-linux-x64": "1.0.57-4",
+ "@github/copilot-linuxmusl-arm64": "1.0.57-4",
+ "@github/copilot-linuxmusl-x64": "1.0.57-4",
+ "@github/copilot-win32-arm64": "1.0.57-4",
+ "@github/copilot-win32-x64": "1.0.57-4"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.57-3.tgz",
- "integrity": "sha512-1i0D7EByvaIl71aT60jWE/Rd7chdrcs7uETRp9ZO0dmW74ScWC0fF7qywFfiYY81PCeuHJoKfq0iMcuwt3fb5w==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-NI5FOzEPuvUONclGW818PToyG9EeBeb33E0OzLsCL8649uJketMzr9gjHWAHbF5C67bRF/xZ/DxvrhrEYunWKw==",
"cpu": [
"arm64"
],
@@ -504,9 +504,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.57-3.tgz",
- "integrity": "sha512-s7EuHBRMhaOX+BPR3ys+3OgndNy53csI688Nsi52GiKypx1Ma287ESHEvK9IWZCqtzq3ApxsEdyX8q7enhGstg==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.57-4.tgz",
+ "integrity": "sha512-wvpTb0SLF3wxGOxtUDBLZgePkVxkuw3Bu3nMuazemeKVx03hsGjvvYz8rwAqEEnkonElx3PlADu5eaC6QO//zg==",
"cpu": [
"x64"
],
@@ -521,9 +521,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.57-3.tgz",
- "integrity": "sha512-b/061/sNsj/DVO8cHor75H9iV7rMXHPFdeJhL4grn8TU1ooIpGDCmBafWIYcE6oJGJX88ryLVWOraRS63KSSaA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-4RCCM0PGssfUCZAKxIBLaNXEelW6lw9px0GwCuz7XGvFEYmZmGyC4ArqlrM51alZWnR7MRoaxbRdRmEV2AVdqQ==",
"cpu": [
"arm64"
],
@@ -538,9 +538,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.57-3.tgz",
- "integrity": "sha512-E1faDFGzdlCw3FSh5JlBfBxHQhp9YGk9Qx+a0ZXtTZxQ3WiPoy8DfTaoc6HlT1sZo8dGPvfmJfmCHg52jhmfyA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.57-4.tgz",
+ "integrity": "sha512-BZhp1lYZb/Y/GEb42OdblEHasHdnmwm7Qg7BeR797w34/m7/0m9k//kqggEU1qdVPTvii4SXjdYoelf7CphjRw==",
"cpu": [
"x64"
],
@@ -555,9 +555,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.57-3.tgz",
- "integrity": "sha512-cAOSAtlPXZuJv+zuVkt/YXIwbSoi5aYppxfau3tYDPpiTO/9YAwQYWqXz+GWuqWe3hegzXe6bCeyGDsunhqRtg==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-jZ/RpgbYODgvyDzhgUYBNZzMy8r3MRso2Z8THpRCEYVawScQ7+DM9WWe/2+R8WZ0ipDa+omfm+dFSOPCYSVVug==",
"cpu": [
"arm64"
],
@@ -572,9 +572,9 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.57-3.tgz",
- "integrity": "sha512-jLmUpc8jAT5LH6SQncbyjTEU/bcsM7JrGKUfhV0PeJAU5Z7sOuZekeeVxA/Lq4yI+aBod9cE8kFjB3+KXYK0DQ==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.57-4.tgz",
+ "integrity": "sha512-PXcMGlk9wTPIFAmzfFQreM5azF1V6k4lD4fb2ySg5iYcmtCLV+HG2FlcVwZnJUrNa0da46pmROjzJXT4QPV5Yw==",
"cpu": [
"x64"
],
@@ -589,9 +589,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.57-3.tgz",
- "integrity": "sha512-RRP9+EUdcKz7X12n3Z78hwFTLwCqVi7RML/Mfr30cCvKk0ypMS3Nnlo780exMj2Ba1Da2RHv08DvMvUttqBbFA==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.57-4.tgz",
+ "integrity": "sha512-ChvV8EDHUkiKcCXdrJQksbLrOMcVnl0xerRRMHNHFMGReBfK8+/TyiKgEhw/R3qRI5NnBv7QvBDRhp0KHZ7rqQ==",
"cpu": [
"arm64"
],
@@ -606,9 +606,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.57-3",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.57-3.tgz",
- "integrity": "sha512-SYvCUrtIJzhHuz2XKGDpY5mmCVbaUjF64ZtG/m2zBKsnO9j/Aa9aXw9p3LAk6bbKlXIrHFadE6PTsi0YbOmT9w==",
+ "version": "1.0.57-4",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.57-4.tgz",
+ "integrity": "sha512-xMWYYUL+5HaYy+ddoL6IHVkvLyk2TauXvYUl7b73vqp0elRF2SwEZLFWfYts3L2+wcEkCnYWeOO7lSnT24+FuQ==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index 50d242a7f..5e7d110a7 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -11,7 +11,7 @@
"test": "vitest run"
},
"devDependencies": {
- "@github/copilot": "^1.0.57-3",
+ "@github/copilot": "^1.0.57-4",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",