getCurrent() {
}
/**
- * Target model identifier and optional reasoning effort, summary, and capability overrides.
+ * Target model identifier and optional reasoning effort, summary, capability overrides, and context tier.
*
* Note: the {@code sessionId} field in the params record is overridden
* by the session-scoped wrapper; any value provided is ignored.
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
index 7bb2f8496..8ab022ac9 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
@@ -13,7 +13,7 @@
import javax.annotation.processing.Generated;
/**
- * The currently selected model and reasoning effort for the session.
+ * The currently selected model, reasoning effort, and context tier for the session.
*
* @since 1.0.0
*/
@@ -24,6 +24,8 @@ public record SessionModelGetCurrentResult(
/** Currently active model identifier */
@JsonProperty("modelId") String modelId,
/** Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. */
- @JsonProperty("reasoningEffort") String reasoningEffort
+ @JsonProperty("reasoningEffort") String reasoningEffort,
+ /** Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume. */
+ @JsonProperty("contextTier") ContextTier contextTier
) {
}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
index c5c1cbbe0..4cda275a2 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
@@ -13,7 +13,7 @@
import javax.annotation.processing.Generated;
/**
- * Target model identifier and optional reasoning effort, summary, and capability overrides.
+ * Target model identifier and optional reasoning effort, summary, capability overrides, and context tier.
*
* @since 1.0.0
*/
@@ -30,6 +30,8 @@ public record SessionModelSwitchToParams(
/** Reasoning summary mode to request for supported model clients */
@JsonProperty("reasoningSummary") ReasoningSummary reasoningSummary,
/** Override individual model capabilities resolved by the runtime */
- @JsonProperty("modelCapabilities") ModelCapabilitiesOverride modelCapabilities
+ @JsonProperty("modelCapabilities") ModelCapabilitiesOverride modelCapabilities,
+ /** 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. */
+ @JsonProperty("contextTier") ContextTier contextTier
) {
}
diff --git a/java/src/main/java/com/github/copilot/CopilotSession.java b/java/src/main/java/com/github/copilot/CopilotSession.java
index 64c02d8b8..61bd6bbeb 100644
--- a/java/src/main/java/com/github/copilot/CopilotSession.java
+++ b/java/src/main/java/com/github/copilot/CopilotSession.java
@@ -31,6 +31,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.copilot.generated.AssistantMessageEvent;
import com.github.copilot.generated.rpc.SessionCommandsHandlePendingCommandParams;
+import com.github.copilot.generated.rpc.ContextTier;
import com.github.copilot.generated.rpc.SessionLogParams;
import com.github.copilot.generated.rpc.SessionLogLevel;
import com.github.copilot.generated.rpc.ModelCapabilitiesOverride;
@@ -1696,9 +1697,7 @@ public CompletableFuture abort() {
* @since 1.2.0
*/
public CompletableFuture setModel(String model, String reasoningEffort) {
- ensureNotTerminated();
- return getRpc().model.switchTo(new SessionModelSwitchToParams(sessionId, model, reasoningEffort, null, null))
- .thenApply(r -> null);
+ return setModel(model, reasoningEffort, null, null, null);
}
/**
@@ -1729,7 +1728,7 @@ public CompletableFuture setModel(String model, String reasoningEffort) {
*/
public CompletableFuture setModel(String model, String reasoningEffort,
com.github.copilot.rpc.ModelCapabilitiesOverride modelCapabilities) {
- return setModel(model, reasoningEffort, null, modelCapabilities);
+ return setModel(model, reasoningEffort, null, modelCapabilities, null);
}
/**
@@ -1758,6 +1757,38 @@ public CompletableFuture setModel(String model, String reasoningEffort,
*/
public CompletableFuture setModel(String model, String reasoningEffort, String reasoningSummary,
com.github.copilot.rpc.ModelCapabilitiesOverride modelCapabilities) {
+ return setModel(model, reasoningEffort, reasoningSummary, modelCapabilities, null);
+ }
+
+ /**
+ * Changes the model for this session with optional reasoning effort, reasoning
+ * summary mode, capability overrides, and context tier.
+ *
+ * The new model takes effect for the next message. Conversation history is
+ * preserved.
+ *
+ * @param model
+ * the model ID to switch to (e.g., {@code "gpt-4.1"})
+ * @param reasoningEffort
+ * reasoning effort level; {@code null} to use default
+ * @param reasoningSummary
+ * reasoning summary mode ({@code "none"}, {@code "concise"}, or
+ * {@code "detailed"}); {@code null} to use default. Use
+ * {@code "none"} to suppress summary output regardless of whether
+ * reasoning is enabled.
+ * @param modelCapabilities
+ * per-property overrides for model capabilities; {@code null} to use
+ * runtime defaults
+ * @param contextTier
+ * context window tier ({@code "default"} or
+ * {@code "long_context"}); {@code null} to use default
+ * @return a future that completes when the model switch is acknowledged
+ * @throws IllegalStateException
+ * if this session has been terminated
+ * @since 1.3.0
+ */
+ public CompletableFuture setModel(String model, String reasoningEffort, String reasoningSummary,
+ com.github.copilot.rpc.ModelCapabilitiesOverride modelCapabilities, String contextTier) {
ensureNotTerminated();
ModelCapabilitiesOverride generatedCapabilities = null;
if (modelCapabilities != null) {
@@ -1777,8 +1808,9 @@ public CompletableFuture setModel(String model, String reasoningEffort, St
var generatedReasoningSummary = reasoningSummary == null
? null
: com.github.copilot.generated.rpc.ReasoningSummary.fromValue(reasoningSummary);
+ var generatedContextTier = contextTier == null ? null : ContextTier.fromValue(contextTier);
return getRpc().model.switchTo(new SessionModelSwitchToParams(sessionId, model, reasoningEffort,
- generatedReasoningSummary, generatedCapabilities)).thenApply(r -> null);
+ generatedReasoningSummary, generatedCapabilities, generatedContextTier)).thenApply(r -> null);
}
/**
diff --git a/java/src/test/java/com/github/copilot/RpcWrappersTest.java b/java/src/test/java/com/github/copilot/RpcWrappersTest.java
index 7b01e1d38..ff48d4897 100644
--- a/java/src/test/java/com/github/copilot/RpcWrappersTest.java
+++ b/java/src/test/java/com/github/copilot/RpcWrappersTest.java
@@ -183,7 +183,8 @@ void sessionRpc_model_switchTo_merges_sessionId_with_extra_params() {
var session = new SessionRpc(stub, "sess-xyz");
// switchTo takes extra params beyond sessionId
- var switchParams = new SessionModelSwitchToParams(null, "gpt-5", null, null, null);
+ var switchParams = new SessionModelSwitchToParams(null, "gpt-5", null, null, null,
+ ContextTier.LONG_CONTEXT);
session.model.switchTo(switchParams);
assertEquals(1, stub.calls.size());
@@ -195,6 +196,7 @@ void sessionRpc_model_switchTo_merges_sessionId_with_extra_params() {
var node = (com.fasterxml.jackson.databind.node.ObjectNode) params;
assertEquals("sess-xyz", node.get("sessionId").asText());
assertEquals("gpt-5", node.get("modelId").asText());
+ assertEquals("long_context", node.get("contextTier").asText());
}
@Test
diff --git a/java/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java b/java/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
index d34fa76b1..4d2dc949a 100644
--- a/java/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
+++ b/java/src/test/java/com/github/copilot/generated/rpc/GeneratedRpcRecordsCoverageTest.java
@@ -321,12 +321,14 @@ void sessionModelGetCurrentParams_record() {
@Test
void sessionModelSwitchToParams_record() {
- var params = new SessionModelSwitchToParams("sess-32", "claude-sonnet-4.5", "high", null, null);
+ var params = new SessionModelSwitchToParams("sess-32", "claude-sonnet-4.5", "high", null, null,
+ ContextTier.LONG_CONTEXT);
assertEquals("sess-32", params.sessionId());
assertEquals("claude-sonnet-4.5", params.modelId());
assertEquals("high", params.reasoningEffort());
assertNull(params.reasoningSummary());
assertNull(params.modelCapabilities());
+ assertEquals(ContextTier.LONG_CONTEXT, params.contextTier());
}
@Test
@@ -720,8 +722,9 @@ void sessionModeSetResult_enum() {
@Test
void sessionModelGetCurrentResult_record() {
- var result = new SessionModelGetCurrentResult("claude-sonnet-4.5", null);
+ var result = new SessionModelGetCurrentResult("claude-sonnet-4.5", null, ContextTier.LONG_CONTEXT);
assertEquals("claude-sonnet-4.5", result.modelId());
+ assertEquals(ContextTier.LONG_CONTEXT, result.contextTier());
}
@Test
@@ -957,9 +960,11 @@ void sessionModelSwitchToParams_nested_records() {
var limits = new ModelCapabilitiesOverrideLimits(100000L, 8192L, 128000L, limitsVision);
var supports = new ModelCapabilitiesOverrideSupports(true, true);
var capabilities = new ModelCapabilitiesOverride(supports, limits);
- var params = new SessionModelSwitchToParams("sess-m", "gpt-5", null, null, capabilities);
+ var params = new SessionModelSwitchToParams("sess-m", "gpt-5", null, null, capabilities,
+ ContextTier.DEFAULT);
assertEquals("gpt-5", params.modelId());
+ assertEquals(ContextTier.DEFAULT, params.contextTier());
assertNotNull(params.modelCapabilities());
assertTrue(params.modelCapabilities().supports().vision());
assertTrue(params.modelCapabilities().supports().reasoningEffort());
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 602ee76a0..5c01060aa 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -266,13 +266,9 @@ export type ContentFilterMode =
/** Remove characters that can hide directives. */
| "hidden_characters";
/**
- * Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume.
- *
- * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
- * via the `definition` "ModelCurrentContextTier".
+ * Context window tier for models that support tiered context windows.
*/
-/** @experimental */
-export type ModelCurrentContextTier =
+export type ContextTier =
/** Use the model's default context window. */
| "default"
/** Pin the session to the long-context tier when supported. */
@@ -2841,7 +2837,7 @@ export interface CurrentModel {
* Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot.
*/
reasoningEffort?: string;
- contextTier?: ModelCurrentContextTier;
+ contextTier?: ContextTier;
}
/**
* Lightweight metadata for a currently initialized session tool
@@ -4952,11 +4948,7 @@ export interface 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.
*/
- contextTier?: /** Use the model's default context window. */
- | "default"
- /** Pin the session to the long-context tier when supported. */
- | "long_context"
- | null;
+ contextTier?: ContextTier | null;
}
/**
* 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/src/types.ts b/nodejs/src/types.ts
index 75aa5159f..2ba1a3660 100644
--- a/nodejs/src/types.ts
+++ b/nodejs/src/types.ts
@@ -14,10 +14,10 @@ import type {
SessionEvent as GeneratedSessionEvent,
} from "./generated/session-events.js";
import type { CopilotSession } from "./session.js";
-import type { RemoteSessionMode } from "./generated/rpc.js";
+import type { ContextTier, RemoteSessionMode } from "./generated/rpc.js";
import type { OpenCanvasInstance } from "./generated/rpc.js";
import type { ToolSet } from "./toolSet.js";
-export type { RemoteSessionMode } from "./generated/rpc.js";
+export type { ContextTier, RemoteSessionMode } from "./generated/rpc.js";
export type SessionEvent = GeneratedSessionEvent;
export type { ReasoningSummary } from "./generated/session-events.js";
export type { SessionFsProvider } from "./sessionFsProvider.js";
@@ -1540,12 +1540,6 @@ export interface LargeToolOutputConfig {
*/
export type ReasoningEffort = "low" | "medium" | "high" | "xhigh";
-/**
- * Context window tier for the session. "long_context" pins the session to the
- * long-context tier when the selected model supports it.
- */
-export type ContextTier = "default" | "long_context";
-
/**
* Stable extension identity for session participants that provide canvases.
*/
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 694a6a267..5186a30a6 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -1051,13 +1051,15 @@ def to_dict(self) -> dict:
return result
# Experimental: this type is part of an experimental API and may change or be removed.
-class ModelCurrentContextTier(Enum):
+class ContextTier(Enum):
"""Context tier currently pinned for the session, when one is set. Reflects
`Session.getContextTier()`, restored from the session journal on resume.
"""
DEFAULT = "default"
LONG_CONTEXT = "long_context"
+ModelCurrentContextTier = ContextTier
+
class DiscoveredMCPServerType(Enum):
"""Server transport type: stdio, http, sse (deprecated), or memory"""
@@ -7467,7 +7469,7 @@ def to_dict(self) -> dict:
class CurrentModel:
"""The currently selected model, reasoning effort, and context tier for the session."""
- context_tier: ModelCurrentContextTier | None = None
+ context_tier: ContextTier | None = None
"""Context tier currently pinned for the session, when one is set. Reflects
`Session.getContextTier()`, restored from the session journal on resume.
"""
@@ -7483,7 +7485,7 @@ class CurrentModel:
@staticmethod
def from_dict(obj: Any) -> 'CurrentModel':
assert isinstance(obj, dict)
- context_tier = from_union([ModelCurrentContextTier, from_none], obj.get("contextTier"))
+ context_tier = from_union([ContextTier, from_none], obj.get("contextTier"))
model_id = from_union([from_str, from_none], obj.get("modelId"))
reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort"))
return CurrentModel(context_tier, model_id, reasoning_effort)
@@ -7491,7 +7493,7 @@ def from_dict(obj: Any) -> 'CurrentModel':
def to_dict(self) -> dict:
result: dict = {}
if self.context_tier is not None:
- result["contextTier"] = from_union([lambda x: to_enum(ModelCurrentContextTier, x), from_none], self.context_tier)
+ result["contextTier"] = from_union([lambda x: to_enum(ContextTier, x), from_none], self.context_tier)
if self.model_id is not None:
result["modelId"] = from_union([from_str, from_none], self.model_id)
if self.reasoning_effort is not None:
@@ -15402,7 +15404,7 @@ class ModelSwitchToRequest:
model_id: str
"""Model identifier to switch to"""
- context_tier: ModelCurrentContextTier | None = None
+ 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.
@@ -15420,7 +15422,7 @@ class ModelSwitchToRequest:
def from_dict(obj: Any) -> 'ModelSwitchToRequest':
assert isinstance(obj, dict)
model_id = from_str(obj.get("modelId"))
- context_tier = from_union([ModelCurrentContextTier, from_none], obj.get("contextTier"))
+ context_tier = from_union([ContextTier, from_none], obj.get("contextTier"))
model_capabilities = from_union([ModelCapabilitiesOverride.from_dict, from_none], obj.get("modelCapabilities"))
reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort"))
reasoning_summary = from_union([ReasoningSummary, from_none], obj.get("reasoningSummary"))
@@ -15430,7 +15432,7 @@ def to_dict(self) -> dict:
result: dict = {}
result["modelId"] = from_str(self.model_id)
if self.context_tier is not None:
- result["contextTier"] = from_union([lambda x: to_enum(ModelCurrentContextTier, x), from_none], self.context_tier)
+ result["contextTier"] = from_union([lambda x: to_enum(ContextTier, x), from_none], self.context_tier)
if self.model_capabilities is not None:
result["modelCapabilities"] = from_union([lambda x: to_class(ModelCapabilitiesOverride, x), from_none], self.model_capabilities)
if self.reasoning_effort is not None:
@@ -15850,7 +15852,7 @@ class RPC:
model_capabilities_override_limits_vision: ModelCapabilitiesOverrideLimitsVision
model_capabilities_override_supports: ModelCapabilitiesOverrideSupports
model_capabilities_supports: ModelCapabilitiesSupports
- model_current_context_tier: ModelCurrentContextTier
+ model_current_context_tier: ContextTier
model_list: ModelList
model_list_request: ModelListRequest
model_picker_category: ModelPickerCategory
@@ -16436,7 +16438,7 @@ def from_dict(obj: Any) -> 'RPC':
model_capabilities_override_limits_vision = ModelCapabilitiesOverrideLimitsVision.from_dict(obj.get("ModelCapabilitiesOverrideLimitsVision"))
model_capabilities_override_supports = ModelCapabilitiesOverrideSupports.from_dict(obj.get("ModelCapabilitiesOverrideSupports"))
model_capabilities_supports = ModelCapabilitiesSupports.from_dict(obj.get("ModelCapabilitiesSupports"))
- model_current_context_tier = ModelCurrentContextTier(obj.get("ModelCurrentContextTier"))
+ model_current_context_tier = ContextTier(obj.get("ModelCurrentContextTier"))
model_list = ModelList.from_dict(obj.get("ModelList"))
model_list_request = ModelListRequest.from_dict(obj.get("ModelListRequest"))
model_picker_category = ModelPickerCategory(obj.get("ModelPickerCategory"))
@@ -17022,7 +17024,7 @@ def to_dict(self) -> dict:
result["ModelCapabilitiesOverrideLimitsVision"] = to_class(ModelCapabilitiesOverrideLimitsVision, self.model_capabilities_override_limits_vision)
result["ModelCapabilitiesOverrideSupports"] = to_class(ModelCapabilitiesOverrideSupports, self.model_capabilities_override_supports)
result["ModelCapabilitiesSupports"] = to_class(ModelCapabilitiesSupports, self.model_capabilities_supports)
- result["ModelCurrentContextTier"] = to_enum(ModelCurrentContextTier, self.model_current_context_tier)
+ result["ModelCurrentContextTier"] = to_enum(ContextTier, self.model_current_context_tier)
result["ModelList"] = to_class(ModelList, self.model_list)
result["ModelListRequest"] = to_class(ModelListRequest, self.model_list_request)
result["ModelPickerCategory"] = to_enum(ModelPickerCategory, self.model_picker_category)
diff --git a/python/copilot/session.py b/python/copilot/session.py
index f9bbb24c3..c61ca6add 100644
--- a/python/copilot/session.py
+++ b/python/copilot/session.py
@@ -39,6 +39,7 @@
ExternalToolTextResultForLlm,
HandlePendingToolCallRequest,
LogRequest,
+ ContextTier as _RpcContextTier,
ModelSwitchToRequest,
PermissionDecision,
PermissionDecisionApproveOnce,
@@ -2394,6 +2395,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 +2411,7 @@ 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.
model_capabilities: Override individual model capabilities resolved by the runtime.
Raises:
@@ -2434,6 +2437,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 39157f858..238eaae00 100644
--- a/rust/src/generated/api_types.rs
+++ b/rust/src/generated/api_types.rs
@@ -1796,7 +1796,7 @@ pub struct CopilotApiTokenAuthInfo {
pub struct CurrentModel {
/// Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume.
#[serde(skip_serializing_if = "Option::is_none")]
- pub context_tier: Option,
+ pub context_tier: Option,
/// Currently active model identifier
#[serde(skip_serializing_if = "Option::is_none")]
pub model_id: Option,
@@ -4051,7 +4051,7 @@ pub struct ModelsListRequest {
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.
#[serde(skip_serializing_if = "Option::is_none")]
- pub context_tier: Option,
+ pub context_tier: Option,
/// Override individual model capabilities resolved by the runtime
#[serde(skip_serializing_if = "Option::is_none")]
pub model_capabilities: Option,
@@ -10117,7 +10117,7 @@ pub struct SessionModelGetCurrentParams {
pub struct SessionModelGetCurrentResult {
/// Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume.
#[serde(skip_serializing_if = "Option::is_none")]
- pub context_tier: Option,
+ pub context_tier: Option,
/// Currently active model identifier
#[serde(skip_serializing_if = "Option::is_none")]
pub model_id: Option,
@@ -13155,16 +13155,9 @@ pub enum CopilotApiTokenAuthInfoType {
CopilotApiToken,
}
-/// Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume.
-///
-///
-///
-/// **Experimental.** This type is part of an experimental wire-protocol surface
-/// and may change or be removed in future SDK or CLI releases.
-///
-///
+/// Context window tier for models that support tiered context windows.
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
-pub enum ModelCurrentContextTier {
+pub enum ContextTier {
/// Use the model's default context window.
#[serde(rename = "default")]
Default,
@@ -13927,20 +13920,6 @@ pub enum ModelPolicyState {
Unknown,
}
-#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
-pub enum ModelSwitchToRequestContextTier {
- /// Use the model's default context window.
- #[serde(rename = "default")]
- Default,
- /// Pin the session to the long-context tier when supported.
- #[serde(rename = "long_context")]
- LongContext,
- /// Unknown variant for forward compatibility.
- #[default]
- #[serde(other)]
- Unknown,
-}
-
/// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch).
///
///
diff --git a/rust/src/session.rs b/rust/src/session.rs
index 6a1e4f92c..fc1999602 100644
--- a/rust/src/session.rs
+++ b/rust/src/session.rs
@@ -522,6 +522,7 @@ impl Session {
let opts = opts.unwrap_or_default();
let request = ModelSwitchToRequest {
model_id: model.to_string(),
+ context_tier: opts.context_tier,
reasoning_effort: opts.reasoning_effort,
reasoning_summary: opts.reasoning_summary,
model_capabilities: opts.model_capabilities,
diff --git a/rust/src/types.rs b/rust/src/types.rs
index e4b9d48e2..df578f624 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::canvas::{CanvasDeclaration, CanvasHandler};
+/// Context window tier for models that support tiered context windows.
+pub use crate::generated::api_types::ContextTier;
use crate::generated::api_types::OpenCanvasInstance;
use crate::generated::session_events::ReasoningSummary;
use crate::handler::{
@@ -1157,9 +1159,8 @@ pub struct SessionConfig {
/// reasoning summaries. Use [`ReasoningSummary::None`] to suppress
/// summary output regardless of whether reasoning is enabled.
pub reasoning_summary: Option
,
- /// Context window tier for models that support it. Use `"long_context"`
- /// to pin the session to the long-context tier.
- pub context_tier: Option,
+ /// Context window tier for models that support it.
+ pub context_tier: Option,
/// Enable streaming token deltas via `assistant.message_delta` events.
pub streaming: Option,
/// Custom system message configuration.
@@ -1828,9 +1829,9 @@ impl SessionConfig {
self
}
- /// Set the context window tier (e.g. `"default"`, `"long_context"`).
- pub fn with_context_tier(mut self, tier: impl Into) -> Self {
- self.context_tier = Some(tier.into());
+ /// Set [`context_tier`](Self::context_tier).
+ pub fn with_context_tier(mut self, tier: ContextTier) -> Self {
+ self.context_tier = Some(tier);
self
}
@@ -2190,9 +2191,8 @@ pub struct ResumeSessionConfig {
/// [`ReasoningSummary::None`] to suppress summary output regardless of
/// whether reasoning is enabled.
pub reasoning_summary: Option,
- /// Context window tier to apply after resuming the session. Use
- /// `"long_context"` to pin the session to the long-context tier.
- pub context_tier: Option,
+ /// Context window tier to apply after resuming the session.
+ pub context_tier: Option,
/// Enable streaming token deltas.
pub streaming: Option,
/// Re-supply the system message so the agent retains workspace context
@@ -2755,10 +2755,9 @@ impl ResumeSessionConfig {
self
}
- /// Set the context window tier to apply on resume (e.g. `"default"`,
- /// `"long_context"`).
- pub fn with_context_tier(mut self, tier: impl Into) -> Self {
- self.context_tier = Some(tier.into());
+ /// Set [`context_tier`](Self::context_tier).
+ pub fn with_context_tier(mut self, tier: ContextTier) -> Self {
+ self.context_tier = Some(tier);
self
}
@@ -3267,6 +3266,8 @@ pub struct SetModelOptions {
/// [`ReasoningSummary::None`] to suppress summary output regardless of
/// whether reasoning is enabled.
pub reasoning_summary: Option,
+ /// Context window tier for the new model.
+ 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 +3287,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,
@@ -4259,10 +4266,10 @@ mod tests {
use super::{
AgentMode, Attachment, AttachmentLineRange, AttachmentSelectionPosition,
- AttachmentSelectionRange, ConnectionState, CustomAgentConfig, DeliveryMode, ExtensionInfo,
- GitHubReferenceType, InfiniteSessionConfig, LargeToolOutputConfig, ProviderConfig,
- ReasoningSummary, ResumeSessionConfig, SessionConfig, SessionEvent, SessionId,
- SystemMessageConfig, Tool, ToolBinaryResult, ToolResult, ToolResultExpanded,
+ AttachmentSelectionRange, ConnectionState, ContextTier, CustomAgentConfig, DeliveryMode,
+ ExtensionInfo, GitHubReferenceType, InfiniteSessionConfig, LargeToolOutputConfig,
+ ProviderConfig, ReasoningSummary, ResumeSessionConfig, SessionConfig, SessionEvent,
+ SessionId, SystemMessageConfig, Tool, ToolBinaryResult, ToolResult, ToolResultExpanded,
ToolResultResponse, ensure_attachment_display_names,
};
use crate::generated::session_events::TypedSessionEvent;
@@ -4606,7 +4613,7 @@ mod tests {
.with_client_name("test-app")
.with_reasoning_effort("medium")
.with_reasoning_summary(ReasoningSummary::Concise)
- .with_context_tier("long_context")
+ .with_context_tier(ContextTier::LongContext)
.with_streaming(true)
.with_tools([Tool::new("greet")])
.with_available_tools(["bash", "view"])
@@ -4630,7 +4637,7 @@ mod tests {
assert_eq!(cfg.client_name.as_deref(), Some("test-app"));
assert_eq!(cfg.reasoning_effort.as_deref(), Some("medium"));
assert_eq!(cfg.reasoning_summary, Some(ReasoningSummary::Concise));
- assert_eq!(cfg.context_tier.as_deref(), Some("long_context"));
+ assert_eq!(cfg.context_tier, Some(ContextTier::LongContext));
assert_eq!(cfg.streaming, Some(true));
assert_eq!(cfg.tools.as_ref().map(|t| t.len()), Some(1));
assert_eq!(
@@ -4672,7 +4679,7 @@ mod tests {
let cfg = ResumeSessionConfig::new(SessionId::from("sess-2"))
.with_client_name("test-app")
.with_reasoning_summary(ReasoningSummary::None)
- .with_context_tier("default")
+ .with_context_tier(ContextTier::Default)
.with_streaming(true)
.with_tools([Tool::new("greet")])
.with_available_tools(["bash", "view"])
@@ -4696,7 +4703,7 @@ mod tests {
assert_eq!(cfg.session_id.as_str(), "sess-2");
assert_eq!(cfg.client_name.as_deref(), Some("test-app"));
assert_eq!(cfg.reasoning_summary, Some(ReasoningSummary::None));
- assert_eq!(cfg.context_tier.as_deref(), Some("default"));
+ assert_eq!(cfg.context_tier, Some(ContextTier::Default));
assert_eq!(cfg.streaming, Some(true));
assert_eq!(cfg.tools.as_ref().map(|t| t.len()), Some(1));
assert_eq!(
diff --git a/rust/src/wire.rs b/rust/src/wire.rs
index de40720b2..42f511f82 100644
--- a/rust/src/wire.rs
+++ b/rust/src/wire.rs
@@ -24,7 +24,7 @@ use crate::generated::api_types::{
};
use crate::generated::session_events::ReasoningSummary;
use crate::types::{
- CloudSessionOptions, CustomAgentConfig, DefaultAgentConfig, ExtensionInfo,
+ CloudSessionOptions, ContextTier, CustomAgentConfig, DefaultAgentConfig, ExtensionInfo,
InfiniteSessionConfig, LargeToolOutputConfig, McpServerConfig, ProviderConfig, SessionId,
SystemMessageConfig, Tool,
};
@@ -55,7 +55,7 @@ pub(crate) struct SessionCreateWire {
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_summary: Option,
#[serde(skip_serializing_if = "Option::is_none")]
- pub context_tier: Option,
+ pub context_tier: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub streaming: Option,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -161,7 +161,7 @@ pub(crate) struct SessionResumeWire {
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_summary: Option,
#[serde(skip_serializing_if = "Option::is_none")]
- pub context_tier: Option,
+ pub context_tier: Option,
#[serde(skip_serializing_if = "Option::is_none")]
pub streaming: Option,
#[serde(skip_serializing_if = "Option::is_none")]
diff --git a/rust/tests/session_test.rs b/rust/tests/session_test.rs
index 786ba97de..b4cb1c52b 100644
--- a/rust/tests/session_test.rs
+++ b/rust/tests/session_test.rs
@@ -6,6 +6,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
use async_trait::async_trait;
+use github_copilot_sdk::ContextTier;
use github_copilot_sdk::canvas::{CanvasDeclaration, CanvasHandler, CanvasResult};
use github_copilot_sdk::generated::api_types::{
CanvasInstanceAvailability, CanvasProviderInvokeActionRequest, CanvasProviderOpenRequest,
@@ -1290,7 +1291,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 +1304,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,
From 62efeec1b7d986123268df1907dabc77970cbd1e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 29 May 2026 22:06:26 +0000
Subject: [PATCH 2/2] Regenerate Java codegen output
Auto-committed by java-codegen-check workflow.
---
.../com/github/copilot/generated/rpc/SessionModelApi.java | 2 +-
.../copilot/generated/rpc/SessionModelGetCurrentResult.java | 6 ++----
.../copilot/generated/rpc/SessionModelSwitchToParams.java | 6 ++----
3 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelApi.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelApi.java
index d4c0a4e34..eda751b3e 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelApi.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelApi.java
@@ -40,7 +40,7 @@ public CompletableFuture getCurrent() {
}
/**
- * Target model identifier and optional reasoning effort, summary, capability overrides, and context tier.
+ * Target model identifier and optional reasoning effort, summary, and capability overrides.
*
* Note: the {@code sessionId} field in the params record is overridden
* by the session-scoped wrapper; any value provided is ignored.
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
index 8ab022ac9..7bb2f8496 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelGetCurrentResult.java
@@ -13,7 +13,7 @@
import javax.annotation.processing.Generated;
/**
- * The currently selected model, reasoning effort, and context tier for the session.
+ * The currently selected model and reasoning effort for the session.
*
* @since 1.0.0
*/
@@ -24,8 +24,6 @@ public record SessionModelGetCurrentResult(
/** Currently active model identifier */
@JsonProperty("modelId") String modelId,
/** Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. */
- @JsonProperty("reasoningEffort") String reasoningEffort,
- /** Context tier currently pinned for the session, when one is set. Reflects `Session.getContextTier()`, restored from the session journal on resume. */
- @JsonProperty("contextTier") ContextTier contextTier
+ @JsonProperty("reasoningEffort") String reasoningEffort
) {
}
diff --git a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
index 4cda275a2..c5c1cbbe0 100644
--- a/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
+++ b/java/src/generated/java/com/github/copilot/generated/rpc/SessionModelSwitchToParams.java
@@ -13,7 +13,7 @@
import javax.annotation.processing.Generated;
/**
- * Target model identifier and optional reasoning effort, summary, capability overrides, and context tier.
+ * Target model identifier and optional reasoning effort, summary, and capability overrides.
*
* @since 1.0.0
*/
@@ -30,8 +30,6 @@ public record SessionModelSwitchToParams(
/** Reasoning summary mode to request for supported model clients */
@JsonProperty("reasoningSummary") ReasoningSummary reasoningSummary,
/** Override individual model capabilities resolved by the runtime */
- @JsonProperty("modelCapabilities") ModelCapabilitiesOverride modelCapabilities,
- /** 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. */
- @JsonProperty("contextTier") ContextTier contextTier
+ @JsonProperty("modelCapabilities") ModelCapabilitiesOverride modelCapabilities
) {
}