,
}
-/// Credentials to store after successful authentication
+/// Credentials to validate and store. Omit login to resolve the authenticated user from the token.
///
///
///
@@ -1416,8 +1416,9 @@ pub struct AccountGetQuotaResult {
pub struct AccountLoginRequest {
/// GitHub host URL
pub host: String,
- /// User login/username
- pub login: String,
+ /// User login/username. When omitted, the runtime validates the token and resolves the login from GitHub.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub login: Option,
/// GitHub authentication token
pub token: String,
}
@@ -31256,6 +31257,9 @@ pub enum PermissionModeSource {
/// The mode was set by confirming autopilot behavior.
#[serde(rename = "autopilot_confirmation")]
AutopilotConfirmation,
+ /// The mode was set at startup by the `defaultPermissionMode` user setting.
+ #[serde(rename = "user_setting")]
+ UserSetting,
/// The mode was set through an RPC caller.
#[serde(rename = "rpc")]
Rpc,
@@ -31328,6 +31332,9 @@ pub enum PermissionsSetApproveAllSource {
/// Allow-all was enabled by confirming autopilot behavior.
#[serde(rename = "autopilot_confirmation")]
AutopilotConfirmation,
+ /// Allow-all was enabled at startup by the `defaultPermissionMode` user setting.
+ #[serde(rename = "user_setting")]
+ UserSetting,
/// Allow-all was enabled through an RPC caller.
#[serde(rename = "rpc")]
Rpc,
diff --git a/rust/src/generated/rpc.rs b/rust/src/generated/rpc.rs
index 1e3d559baa..c955637e31 100644
--- a/rust/src/generated/rpc.rs
+++ b/rust/src/generated/rpc.rs
@@ -345,13 +345,13 @@ impl<'a> ClientRpcAccount<'a> {
Ok(serde_json::from_value(_value)?)
}
- /// Stores authentication credentials after successful login (e.g., device code flow).
+ /// Validates and stores authentication credentials. When login is omitted, resolves the authenticated user from the token before persistence.
///
/// Wire method: `account.login`.
///
/// # Parameters
///
- /// * `params` - Credentials to store after successful authentication
+ /// * `params` - Credentials to validate and store. Omit login to resolve the authenticated user from the token.
///
/// # Returns
///
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index bf1ebde84e..18a9ac9a61 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.81-5",
+ "@github/copilot": "^1.0.81-6",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
@@ -472,8 +472,8 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.81-5",
- "integrity": "sha512-CLZNjPx4lsseIlfXxmLCGbr4IbfjJmNFPiEzkuuPJBH/Nubw3ibKbJtqSMRiHaNTS4LVmVFkGzqZ7NeUE3MjgA==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-hT29nRkf0EJE3N6lqeLOPszbdEyALZ+fjYG9zKX5a3L5r+o+m4/KF+8l2gn2yORNqOzwUYNj2vnVzKqeYYNLGg==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
@@ -483,19 +483,19 @@
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.81-5",
- "@github/copilot-darwin-x64": "1.0.81-5",
- "@github/copilot-linux-arm64": "1.0.81-5",
- "@github/copilot-linux-x64": "1.0.81-5",
- "@github/copilot-linuxmusl-arm64": "1.0.81-5",
- "@github/copilot-linuxmusl-x64": "1.0.81-5",
- "@github/copilot-win32-arm64": "1.0.81-5",
- "@github/copilot-win32-x64": "1.0.81-5"
+ "@github/copilot-darwin-arm64": "1.0.81-6",
+ "@github/copilot-darwin-x64": "1.0.81-6",
+ "@github/copilot-linux-arm64": "1.0.81-6",
+ "@github/copilot-linux-x64": "1.0.81-6",
+ "@github/copilot-linuxmusl-arm64": "1.0.81-6",
+ "@github/copilot-linuxmusl-x64": "1.0.81-6",
+ "@github/copilot-win32-arm64": "1.0.81-6",
+ "@github/copilot-win32-x64": "1.0.81-6"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.81-5",
- "integrity": "sha512-yop7JdAK847INCkUXsFWfuqP72//+xO3b8uXo4T8InWVjdE5DK5G/m9kWzgZfFS7LGoiTGwz2bV54Rfh/gRHVQ==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-nALa4e8Jc/g5ltIHrpHBHByJ5rlgzoZFylZIrkQY+B9vr3L57d5F6fOiTbf/OF9blFQX7artWRE1K0TmowGNCA==",
"cpu": [
"arm64"
],
@@ -510,8 +510,8 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.81-5",
- "integrity": "sha512-s//z4MWiWCGL8437rrODItnoL4FhhQ0bqDnFDRfUoKD7C304b2b2gSm5v4nCLsHjBWp0+jz64zQqNt573g0DYA==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-K+bp799DejrsmxMNyaFAmKo4xnLJXBb8hkv9N8OCQukmTSoRpfqhv2oTDfgVFadwllt+py/FIdxKTZQYvPGGGw==",
"cpu": [
"x64"
],
@@ -526,8 +526,8 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.81-5",
- "integrity": "sha512-Fe7yf5X644SsCGrfvEnW5u/MluA7karsHhprhoRzeyanaUg4A5t9USRSYVUg8xBByXpIILS/uHoFRlRWLUvLzA==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-aEpnfTTjOxpesFo9jqk/phZUivOhNHbdBRfBrS2NiCPrQZFBYUC4wRVo/Xo2PMMQ4J07b6fU7JJQPoUUkKy5Wg==",
"cpu": [
"arm64"
],
@@ -542,8 +542,8 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.81-5",
- "integrity": "sha512-A0D+7zwbo5Zi9uA+5hkVUbM1lN799/AOK4bQbmo9dsyd4Msnm0LVypeMuqPocqFJ0hKQ0jmF50gRkQBXY19DwQ==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-NFqonFfJCyA7d3bNoYeLWUQ69zelPr9TTnLpAHCi3scFZqbEvMBDFxW2XsKWwfYuuR9XzfU7/tgOUgq3gmL5aA==",
"cpu": [
"x64"
],
@@ -558,8 +558,8 @@
}
},
"node_modules/@github/copilot-linuxmusl-arm64": {
- "version": "1.0.81-5",
- "integrity": "sha512-cQqr4K8erxym2TBLZo5h3m81BKzS2rLmzfUZUAmcIqc/pmVqVk9L44csheoDPOxoJJRK2x7acs/OJIXolQEUEQ==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-EE99DFTAgTq6eOFDiiv+OUROD2pDQIrzyyJEfUS9K8JanwNc+Py8vTxrJ0yK0slpJ+Fue5uDRno6c9ys8OM59g==",
"cpu": [
"arm64"
],
@@ -574,8 +574,8 @@
}
},
"node_modules/@github/copilot-linuxmusl-x64": {
- "version": "1.0.81-5",
- "integrity": "sha512-Ip/kBYXveSzlXh/JKDLQ3UE0YiyT+hJ0Z7utxqqocTee30NSpyP8/1xET7mqqezLE2B7/gdgdoPJVxf5xB4idw==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-90HRKx25EjhlQNOCCdbiC0Ck0fSKyp8XUxUoCvuNdoigdUP54ZGS07dkyJiJq9KZaKilxZBSpXiNt8t5ETA2Sg==",
"cpu": [
"x64"
],
@@ -590,8 +590,8 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.81-5",
- "integrity": "sha512-ERTckb1saKW6xZVIFWE5+1aIQPGlAjFers2BSCXWxtwPiIb0Ev/xSMY/gF0R8oH2tWHr06iGC3FnFzXzvn50OQ==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-1dRSHF/7PFzB+AGORg8BJh2n1+N7+sIJDLqozrC9INWFp1t6ercptIXgJTF/V7UZVGQLO4LBBK1HH/QhzUmrfA==",
"cpu": [
"arm64"
],
@@ -606,8 +606,8 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.81-5",
- "integrity": "sha512-rAns726TCJD9fxBRD+ZAdh1+ZwHJncZtSg6T5w3j/7+pMkQUw1RSFxNXx/aeVAwKe+R9gufQWCkSgzaOwDr7kg==",
+ "version": "1.0.81-6",
+ "integrity": "sha512-lIbN1mk6Rm9bWrWU4/UfrC5OCga7XcBi2LBz5roDnNcuG8mKEevDcNOtbEYz/TaJg+WBMoTbGfXBVd1hGy2DTA==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index c4f89970cd..23b30b9aac 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -14,7 +14,7 @@
"node": "^20.19.0 || >=22.12.0"
},
"devDependencies": {
- "@github/copilot": "^1.0.81-5",
+ "@github/copilot": "^1.0.81-6",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"@types/node-forge": "^1.3.14",
From 3aac8955ea4a088c76a00e136769fa320f716f4a Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:06:47 -0400
Subject: [PATCH 2/7] Fix SDK compatibility with updated CLI
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
dotnet/src/Client.cs | 18 ------------------
dotnet/test/E2E/RpcServerMiscE2ETests.cs | 2 +-
go/client.go | 13 -------------
go/internal/e2e/rpc_server_misc_e2e_test.go | 2 +-
.../java/com/github/copilot/CopilotClient.java | 10 +---------
nodejs/src/client.ts | 6 ------
python/copilot/client.py | 8 --------
rust/src/session.rs | 14 --------------
rust/tests/e2e/rpc_server_misc.rs | 2 +-
9 files changed, 4 insertions(+), 71 deletions(-)
diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs
index 5f059fd0ff..86178ba74b 100644
--- a/dotnet/src/Client.cs
+++ b/dotnet/src/Client.cs
@@ -1480,15 +1480,6 @@ public async Task ResumeSessionAsync(string sessionId, ResumeSes
session.SetCapabilities(response.Capabilities);
session.SetOpenCanvases(response.OpenCanvases);
- if (config.McpServers is not null)
- {
- await InvokeRpcAsync(
- connection.Rpc,
- "session.mcp.reloadWithConfig",
- [new ReloadMcpServersRequest(sessionId, new ReloadMcpServersConfig(config.McpServers))],
- cancellationToken);
- }
-
if (config.OnMcpAuthRequest is not null)
{
await session.Rpc.EventLog.RegisterInterestAsync("mcp.oauth_required", cancellationToken);
@@ -2961,13 +2952,6 @@ internal record ResumeSessionResponse(
IList? OpenCanvases = null);
#pragma warning restore GHCP001
- internal record ReloadMcpServersRequest(
- string SessionId,
- ReloadMcpServersConfig Config);
-
- internal record ReloadMcpServersConfig(
- IDictionary McpServers);
-
internal record CommandWireDefinition(
string Name,
string Description);
@@ -3044,8 +3028,6 @@ internal record HooksInvokeResponse(
[JsonSerializable(typeof(CapiSessionOptions))]
[JsonSerializable(typeof(NamedProviderConfig))]
[JsonSerializable(typeof(ProviderModelConfig))]
- [JsonSerializable(typeof(ReloadMcpServersConfig))]
- [JsonSerializable(typeof(ReloadMcpServersRequest))]
[JsonSerializable(typeof(SessionLimitsConfig))]
[JsonSerializable(typeof(ResumeSessionRequest))]
[JsonSerializable(typeof(ResumeSessionResponse))]
diff --git a/dotnet/test/E2E/RpcServerMiscE2ETests.cs b/dotnet/test/E2E/RpcServerMiscE2ETests.cs
index 0838b67185..20993e2ec0 100644
--- a/dotnet/test/E2E/RpcServerMiscE2ETests.cs
+++ b/dotnet/test/E2E/RpcServerMiscE2ETests.cs
@@ -92,7 +92,7 @@ public async Task Should_Login_List_GetCurrentAuth_And_Logout_Account()
var initial = await client.Rpc.Account.GetCurrentAuthAsync();
Assert.Null(initial.AuthInfo);
- var loginResult = await client.Rpc.Account.LoginAsync("https://github.com", login, token);
+ var loginResult = await client.Rpc.Account.LoginAsync("https://github.com", token, login);
Assert.NotNull(loginResult);
var current = await client.Rpc.Account.GetCurrentAuthAsync();
diff --git a/go/client.go b/go/client.go
index 0852f99332..fb02897f91 100644
--- a/go/client.go
+++ b/go/client.go
@@ -1356,19 +1356,6 @@ func (c *Client) ResumeSessionWithOptions(ctx context.Context, sessionID string,
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
- if config.MCPServers != nil {
- internalSessionRPC := rpc.NewInternalSessionRPC(c.client, sessionID)
- _, err := internalSessionRPC.MCP.ReloadWithConfig(ctx, &rpc.MCPReloadWithConfigRequest{
- Config: map[string]any{"mcpServers": config.MCPServers},
- })
- if err != nil {
- c.sessionsMux.Lock()
- delete(c.sessions, sessionID)
- c.sessionsMux.Unlock()
- return nil, fmt.Errorf("failed to reload MCP servers after resume: %w", err)
- }
- }
-
if config.OnMCPAuthRequest != nil {
if _, err := c.client.Request(ctx, "session.eventLog.registerInterest", map[string]any{
"sessionId": sessionID,
diff --git a/go/internal/e2e/rpc_server_misc_e2e_test.go b/go/internal/e2e/rpc_server_misc_e2e_test.go
index 37ec57e1ba..9607994676 100644
--- a/go/internal/e2e/rpc_server_misc_e2e_test.go
+++ b/go/internal/e2e/rpc_server_misc_e2e_test.go
@@ -131,7 +131,7 @@ func TestRpcServerMisc(t *testing.T) {
login, err := client.RPC.Account.Login(t.Context(), &rpc.AccountLoginRequest{
Host: "https://github.com",
- Login: "go-account-user",
+ Login: rpcPtr("go-account-user"),
Token: "go-account-token",
})
if err != nil {
diff --git a/java/sdk/src/main/java/com/github/copilot/CopilotClient.java b/java/sdk/src/main/java/com/github/copilot/CopilotClient.java
index 3546f88636..cdd1b9ff3c 100644
--- a/java/sdk/src/main/java/com/github/copilot/CopilotClient.java
+++ b/java/sdk/src/main/java/com/github/copilot/CopilotClient.java
@@ -40,8 +40,6 @@
import com.github.copilot.generated.rpc.GitHubTelemetryNotification;
import com.github.copilot.generated.rpc.ServerRpc;
import com.github.copilot.generated.rpc.SessionEventLogRegisterInterestParams;
-import com.github.copilot.generated.rpc.SessionMcpReloadWithConfigParams;
-import com.github.copilot.generated.rpc.SessionMcpReloadWithConfigResult;
import com.github.copilot.rpc.DeleteSessionResponse;
import com.github.copilot.rpc.GetAuthStatusResponse;
import com.github.copilot.rpc.GetLastSessionIdResponse;
@@ -1148,17 +1146,11 @@ public CompletableFuture resumeSession(String sessionId, ResumeS
rpcNanos);
String returnedId = response.sessionId();
String interestSessionId = returnedId != null ? returnedId : sessionId;
- CompletableFuture> reload = config.getMcpServers() != null
- ? connection.rpc.invoke("session.mcp.reloadWithConfig",
- new SessionMcpReloadWithConfigParams(interestSessionId,
- Map.of("mcpServers", config.getMcpServers())),
- SessionMcpReloadWithConfigResult.class)
- : CompletableFuture.completedFuture(null);
CompletableFuture> interest = config.getOnMcpAuthRequest() != null
? session.getRpc().eventLog.registerInterest(new SessionEventLogRegisterInterestParams(
interestSessionId, "mcp.oauth_required"))
: CompletableFuture.completedFuture(null);
- return reload.thenCompose(ignored -> interest).thenApply(interestResult -> {
+ return interest.thenApply(interestResult -> {
logMcpAuthInterestRegistration(interestResult);
return response;
});
diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts
index 988019c723..1be2cbb941 100644
--- a/nodejs/src/client.ts
+++ b/nodejs/src/client.ts
@@ -1919,12 +1919,6 @@ export class CopilotClient {
session["_workspacePath"] = workspacePath;
session.setCapabilities(capabilities);
session.setOpenCanvases(openCanvases ?? []);
- if (config.mcpServers) {
- await this.connection!.sendRequest("session.mcp.reloadWithConfig", {
- sessionId,
- config: { mcpServers: toWireMcpServers(config.mcpServers) },
- });
- }
if (config.onMcpAuthRequest) {
await this.connection!.sendRequest("session.eventLog.registerInterest", {
sessionId,
diff --git a/python/copilot/client.py b/python/copilot/client.py
index 7d9343a657..2654c14477 100644
--- a/python/copilot/client.py
+++ b/python/copilot/client.py
@@ -3423,14 +3423,6 @@ async def resume_session(
session._set_open_canvases(
[OpenCanvasInstance.from_dict(inst) for inst in open_canvases_raw]
)
- if mcp_servers is not None:
- await self._client.request(
- "session.mcp.reloadWithConfig",
- {
- "sessionId": session_id,
- "config": {"mcpServers": _mcp_servers_to_wire(mcp_servers)},
- },
- )
if on_mcp_auth_request is not None:
await self._client.request(
"session.eventLog.registerInterest",
diff --git a/rust/src/session.rs b/rust/src/session.rs
index 2505a2377d..7676c2ad70 100644
--- a/rust/src/session.rs
+++ b/rust/src/session.rs
@@ -1293,20 +1293,6 @@ impl Client {
})
.into());
}
- if let Some(mcp_servers) = wire.mcp_servers.as_ref()
- && let Err(error) = self
- .call(
- "session.mcp.reloadWithConfig",
- Some(serde_json::json!({
- "sessionId": session_id,
- "config": { "mcpServers": mcp_servers },
- })),
- )
- .await
- {
- registration.cleanup(event_loop).await;
- return Err(error);
- }
if has_mcp_auth_handler {
register_mcp_auth_interest(self, &session_id).await?;
}
diff --git a/rust/tests/e2e/rpc_server_misc.rs b/rust/tests/e2e/rpc_server_misc.rs
index 1070347247..e53cce2e59 100644
--- a/rust/tests/e2e/rpc_server_misc.rs
+++ b/rust/tests/e2e/rpc_server_misc.rs
@@ -150,7 +150,7 @@ async fn should_login_list_getcurrentauth_and_logout_account() {
.account()
.login(AccountLoginRequest {
host: "https://github.com".to_string(),
- login: "rust-account-user".to_string(),
+ login: Some("rust-account-user".to_string()),
token: "rust-account-token".to_string(),
})
.await
From 58a63e451929b883a1904c74277c6b3ff1a57d14 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:28:04 -0400
Subject: [PATCH 3/7] Update tests for CLI 1.0.81-6
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
nodejs/test/e2e/factory.e2e.test.ts | 5 +-
nodejs/test/e2e/permissions.e2e.test.ts | 131 ++++++++----------
.../e2e/rpc_ui_ephemeral_query.e2e.test.ts | 5 +-
rust/tests/e2e/rpc_mcp_lifecycle.rs | 2 +
4 files changed, 64 insertions(+), 79 deletions(-)
diff --git a/nodejs/test/e2e/factory.e2e.test.ts b/nodejs/test/e2e/factory.e2e.test.ts
index cddd8e47b0..3baa3fb9c4 100644
--- a/nodejs/test/e2e/factory.e2e.test.ts
+++ b/nodejs/test/e2e/factory.e2e.test.ts
@@ -93,12 +93,9 @@ it.skipIf(isInProcessTransport)(
}
);
-// TODO(cli-1.0.81-2): the subagent request is rejected downstream under CLI 1.0.81-2, so the
-// fixture reports didThrow: true. Re-enable once the runtime fix ships.
-//
// The timeout is generous because the factory abandons its subagent once the runtime has
// accepted the request, so the run settles only after the runtime drains that work.
-it.skip("forwards every declared subagent option to the runtime", async () => {
+it("forwards every declared subagent option to the runtime", async () => {
if (!factoryTestContext) {
throw new Error("Factory E2E requires the stdio transport");
}
diff --git a/nodejs/test/e2e/permissions.e2e.test.ts b/nodejs/test/e2e/permissions.e2e.test.ts
index d7600ed165..b7fa6087a3 100644
--- a/nodejs/test/e2e/permissions.e2e.test.ts
+++ b/nodejs/test/e2e/permissions.e2e.test.ts
@@ -17,8 +17,6 @@ import { approveAll, defineTool, createAttributedPermissionResult } from "../../
import { createSdkTestContext, isInProcessTransport } from "./harness/sdkTestContext.js";
import { getFinalAssistantMessage, getNextEventOfType } from "./harness/sdkTestHelper.js";
-const isWindows = process.platform === "win32";
-
describe("Permission callbacks", async () => {
const { copilotClient: client, workDir } = await createSdkTestContext();
@@ -632,76 +630,67 @@ describe("Permission callbacks", async () => {
}
});
- // TODO(cli-1.0.81-2): CLI 1.0.81-2 no longer matches the location key returned by
- // permissions.locations.resolve when permissions.locations.apply re-resolves it on Windows,
- // so appliedRuleCount comes back as 0. Still covered on Linux and macOS.
- it.skipIf(isWindows)(
- "should invoke permission location and folder trust rpc apis",
- async () => {
- const session = await client.createSession({ onPermissionRequest: approveAll });
- const locationDirectory = await createUniqueWorkDirectory(
- workDir,
- "permission-location"
- );
- const trustedDirectory = await createUniqueWorkDirectory(workDir, "folder-trust");
- const commandIdentifier = `node-permission-location-${Date.now()}`;
- try {
- const resolved = await session.rpc.permissions.locations.resolve({
- workingDirectory: locationDirectory,
- });
- expect(resolved.locationType).toBe("dir");
- expectPathEqual(resolved.locationKey, locationDirectory);
-
- expect(
- (
- await session.rpc.permissions.locations.addToolApproval({
- locationKey: resolved.locationKey,
- approval: {
- kind: "commands",
- commandIdentifiers: [commandIdentifier],
- },
- })
- ).success
- ).toBe(true);
-
- const applied = await session.rpc.permissions.locations.apply({
- workingDirectory: locationDirectory,
- });
- expect(applied.locationType).toBe(resolved.locationType);
- expectPathEqual(applied.locationKey, resolved.locationKey);
- expect(applied.appliedRuleCount).toBeGreaterThanOrEqual(1);
- expect(
- applied.appliedRules.some(
- (rule) => rule.kind === "shell" && rule.argument === commandIdentifier
- )
- ).toBe(true);
-
- expect(
- (
- await session.rpc.permissions.folderTrust.isTrusted({
- path: trustedDirectory,
- })
- ).trusted
- ).toBe(false);
- expect(
- (
- await session.rpc.permissions.folderTrust.addTrusted({
- path: trustedDirectory,
- })
- ).success
- ).toBe(true);
- expect(
- (
- await session.rpc.permissions.folderTrust.isTrusted({
- path: trustedDirectory,
- })
- ).trusted
- ).toBe(true);
- } finally {
- await session.disconnect();
- }
+ it("should invoke permission location and folder trust rpc apis", async () => {
+ const session = await client.createSession({ onPermissionRequest: approveAll });
+ const locationDirectory = await createUniqueWorkDirectory(workDir, "permission-location");
+ const trustedDirectory = await createUniqueWorkDirectory(workDir, "folder-trust");
+ const commandIdentifier = `node-permission-location-${Date.now()}`;
+ try {
+ const resolved = await session.rpc.permissions.locations.resolve({
+ workingDirectory: locationDirectory,
+ });
+ expect(resolved.locationType).toBe("dir");
+ expectPathEqual(resolved.locationKey, locationDirectory);
+
+ expect(
+ (
+ await session.rpc.permissions.locations.addToolApproval({
+ locationKey: resolved.locationKey,
+ approval: {
+ kind: "commands",
+ commandIdentifiers: [commandIdentifier],
+ },
+ })
+ ).success
+ ).toBe(true);
+
+ const applied = await session.rpc.permissions.locations.apply({
+ workingDirectory: locationDirectory,
+ });
+ expect(applied.locationType).toBe(resolved.locationType);
+ expectPathEqual(applied.locationKey, resolved.locationKey);
+ expect(applied.appliedRuleCount).toBeGreaterThanOrEqual(1);
+ expect(
+ applied.appliedRules.some(
+ (rule) => rule.kind === "shell" && rule.argument === commandIdentifier
+ )
+ ).toBe(true);
+
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.isTrusted({
+ path: trustedDirectory,
+ })
+ ).trusted
+ ).toBe(false);
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.addTrusted({
+ path: trustedDirectory,
+ })
+ ).success
+ ).toBe(true);
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.isTrusted({
+ path: trustedDirectory,
+ })
+ ).trusted
+ ).toBe(true);
+ } finally {
+ await session.disconnect();
}
- );
+ });
});
async function createUniqueWorkDirectory(baseDir: string, prefix: string): Promise {
diff --git a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
index be1a25dc6c..662294d70a 100644
--- a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
+++ b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
@@ -9,10 +9,7 @@ import { createSdkTestContext } from "./harness/sdkTestContext.js";
describe("UI ephemeral query RPC", async () => {
const { copilotClient: client } = await createSdkTestContext();
- // TODO(cli-1.0.81-2): CLI 1.0.81-5 still fails session.ui.ephemeralQuery against the
- // recorded snapshot on macOS ("Failed to get response from the AI model"). Re-enable
- // once the runtime fix ships.
- it.skip("should answer ephemeral query", { timeout: 120_000 }, async () => {
+ it("should answer ephemeral query", { timeout: 120_000 }, async () => {
const session = await client.createSession({ onPermissionRequest: approveAll });
try {
const result = await session.rpc.ui.ephemeralQuery({
diff --git a/rust/tests/e2e/rpc_mcp_lifecycle.rs b/rust/tests/e2e/rpc_mcp_lifecycle.rs
index 3955264512..8e5b74c05b 100644
--- a/rust/tests/e2e/rpc_mcp_lifecycle.rs
+++ b/rust/tests/e2e/rpc_mcp_lifecycle.rs
@@ -209,6 +209,7 @@ async fn should_start_and_restart_mcp_server() {
// internal methods generically; it never exercised a supported wire API.
#[tokio::test]
+#[ignore = "blocked on CLI 1.0.81-6 missing session.mcp.reloadWithConfig handler"]
async fn should_reload_mcp_servers_with_config() {
super::support::with_shared_e2e_context(
&E2E,
@@ -252,6 +253,7 @@ async fn should_reload_mcp_servers_with_config() {
}
#[tokio::test]
+#[ignore = "blocked on CLI 1.0.81-6 missing session.mcp.configureGitHub handler"]
async fn should_configure_github_mcp_server() {
super::support::with_shared_e2e_context(
&E2E,
From a8e36fa72f6e9179196b02108fca170b1b491cc9 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:30:16 -0400
Subject: [PATCH 4/7] Re-enable in-process telemetry tests
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
go/internal/e2e/github_telemetry_e2e_test.go | 5 -----
rust/tests/e2e/github_telemetry.rs | 5 -----
2 files changed, 10 deletions(-)
diff --git a/go/internal/e2e/github_telemetry_e2e_test.go b/go/internal/e2e/github_telemetry_e2e_test.go
index 6e1a36383f..aa26ba31f2 100644
--- a/go/internal/e2e/github_telemetry_e2e_test.go
+++ b/go/internal/e2e/github_telemetry_e2e_test.go
@@ -12,11 +12,6 @@ import (
func TestGitHubTelemetryE2E(t *testing.T) {
t.Run("should forward github telemetry for a live session", func(t *testing.T) {
- // TODO(cli-1.0.81-2): CLI 1.0.81-2 does not forward GitHub telemetry notifications
- // over the in-process (FFI) host, mirroring the existing telemetry-configuration
- // limitation. Still covered by the default (stdio) transport.
- testharness.SkipIfInProcess(t, "GitHub telemetry forwarding is not honored in-process")
-
ctx := testharness.NewTestContext(t)
ctx.ConfigureForTest(t)
diff --git a/rust/tests/e2e/github_telemetry.rs b/rust/tests/e2e/github_telemetry.rs
index 02af0e2ae8..2047ee34ff 100644
--- a/rust/tests/e2e/github_telemetry.rs
+++ b/rust/tests/e2e/github_telemetry.rs
@@ -9,11 +9,6 @@ use super::support::{DEFAULT_TEST_TOKEN, with_e2e_context_no_snapshot};
#[tokio::test]
async fn should_forward_github_telemetry_on_session_create() {
- // TODO(cli-1.0.81-2): CLI 1.0.81-2 does not forward GitHub telemetry notifications over
- // the in-process (FFI) host, mirroring the existing telemetry-configuration limitation.
- if super::support::skip_inprocess("GitHub telemetry forwarding is not honored in-process") {
- return;
- }
with_e2e_context_no_snapshot(|ctx| {
Box::pin(async move {
ctx.set_default_copilot_user();
From a4d0706918336058e160e6889c39349e6ec85e62 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:32:15 -0400
Subject: [PATCH 5/7] Scope re-enabled tests to stdio
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
nodejs/test/e2e/factory.e2e.test.ts | 28 +++++++++--------
.../e2e/rpc_ui_ephemeral_query.e2e.test.ts | 30 +++++++++++--------
2 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/nodejs/test/e2e/factory.e2e.test.ts b/nodejs/test/e2e/factory.e2e.test.ts
index 3baa3fb9c4..92c0669753 100644
--- a/nodejs/test/e2e/factory.e2e.test.ts
+++ b/nodejs/test/e2e/factory.e2e.test.ts
@@ -95,20 +95,24 @@ it.skipIf(isInProcessTransport)(
// The timeout is generous because the factory abandons its subagent once the runtime has
// accepted the request, so the run settles only after the runtime drains that work.
-it("forwards every declared subagent option to the runtime", async () => {
- if (!factoryTestContext) {
- throw new Error("Factory E2E requires the stdio transport");
- }
- const { workDir } = factoryTestContext;
- await using session = await setupFactoryExtension(workDir);
+it.skipIf(isInProcessTransport)(
+ "forwards every declared subagent option to the runtime",
+ async () => {
+ if (!factoryTestContext) {
+ throw new Error("Factory E2E requires the stdio transport");
+ }
+ const { workDir } = factoryTestContext;
+ await using session = await setupFactoryExtension(workDir);
- const result = await session.factory.run("forwards-subagent-options");
+ const result = await session.factory.run("forwards-subagent-options");
- expect(result).toMatchObject({
- status: "completed",
- result: { didThrow: false },
- });
-}, 60_000);
+ expect(result).toMatchObject({
+ status: "completed",
+ result: { didThrow: false },
+ });
+ },
+ 60_000
+);
it.skipIf(isInProcessTransport)(
"throws FactoryResumeError with not_found for an unknown run",
diff --git a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
index 662294d70a..30f8acce2d 100644
--- a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
+++ b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
@@ -4,23 +4,27 @@
import { describe, expect, it } from "vitest";
import { approveAll } from "../../src/index.js";
-import { createSdkTestContext } from "./harness/sdkTestContext.js";
+import { createSdkTestContext, isInProcessTransport } from "./harness/sdkTestContext.js";
describe("UI ephemeral query RPC", async () => {
const { copilotClient: client } = await createSdkTestContext();
- it("should answer ephemeral query", { timeout: 120_000 }, async () => {
- const session = await client.createSession({ onPermissionRequest: approveAll });
- try {
- const result = await session.rpc.ui.ephemeralQuery({
- question: "In one word, what is the primary color of a clear daytime sky?",
- });
+ it.skipIf(isInProcessTransport)(
+ "should answer ephemeral query",
+ { timeout: 120_000 },
+ async () => {
+ const session = await client.createSession({ onPermissionRequest: approveAll });
+ try {
+ const result = await session.rpc.ui.ephemeralQuery({
+ question: "In one word, what is the primary color of a clear daytime sky?",
+ });
- expect(result).toBeDefined();
- expect(result.answer.trim()).toBeTruthy();
- expect(result.answer.toLowerCase()).toContain("blue");
- } finally {
- await session.disconnect();
+ expect(result).toBeDefined();
+ expect(result.answer.trim()).toBeTruthy();
+ expect(result.answer.toLowerCase()).toContain("blue");
+ } finally {
+ await session.disconnect();
+ }
}
- });
+ );
});
From f0a91871b37cdf769c464db4fddb188cba1fcf2e Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:34:16 -0400
Subject: [PATCH 6/7] Limit re-enabled Node coverage
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
nodejs/test/e2e/factory.e2e.test.ts | 31 +++++++++----------
.../e2e/rpc_ui_ephemeral_query.e2e.test.ts | 4 ++-
2 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/nodejs/test/e2e/factory.e2e.test.ts b/nodejs/test/e2e/factory.e2e.test.ts
index 92c0669753..cddd8e47b0 100644
--- a/nodejs/test/e2e/factory.e2e.test.ts
+++ b/nodejs/test/e2e/factory.e2e.test.ts
@@ -93,26 +93,25 @@ it.skipIf(isInProcessTransport)(
}
);
+// TODO(cli-1.0.81-2): the subagent request is rejected downstream under CLI 1.0.81-2, so the
+// fixture reports didThrow: true. Re-enable once the runtime fix ships.
+//
// The timeout is generous because the factory abandons its subagent once the runtime has
// accepted the request, so the run settles only after the runtime drains that work.
-it.skipIf(isInProcessTransport)(
- "forwards every declared subagent option to the runtime",
- async () => {
- if (!factoryTestContext) {
- throw new Error("Factory E2E requires the stdio transport");
- }
- const { workDir } = factoryTestContext;
- await using session = await setupFactoryExtension(workDir);
+it.skip("forwards every declared subagent option to the runtime", async () => {
+ if (!factoryTestContext) {
+ throw new Error("Factory E2E requires the stdio transport");
+ }
+ const { workDir } = factoryTestContext;
+ await using session = await setupFactoryExtension(workDir);
- const result = await session.factory.run("forwards-subagent-options");
+ const result = await session.factory.run("forwards-subagent-options");
- expect(result).toMatchObject({
- status: "completed",
- result: { didThrow: false },
- });
- },
- 60_000
-);
+ expect(result).toMatchObject({
+ status: "completed",
+ result: { didThrow: false },
+ });
+}, 60_000);
it.skipIf(isInProcessTransport)(
"throws FactoryResumeError with not_found for an unknown run",
diff --git a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
index 30f8acce2d..7fa1e90f5d 100644
--- a/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
+++ b/nodejs/test/e2e/rpc_ui_ephemeral_query.e2e.test.ts
@@ -9,7 +9,9 @@ import { createSdkTestContext, isInProcessTransport } from "./harness/sdkTestCon
describe("UI ephemeral query RPC", async () => {
const { copilotClient: client } = await createSdkTestContext();
- it.skipIf(isInProcessTransport)(
+ // TODO(cli-1.0.81-2): CLI 1.0.81-6 still fails session.ui.ephemeralQuery against the
+ // recorded snapshot on macOS ("Failed to get response from the AI model").
+ it.skipIf(isInProcessTransport || process.platform === "darwin")(
"should answer ephemeral query",
{ timeout: 120_000 },
async () => {
From e29d20f764dea8ad90c2dc92be2936e1285c5496 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Thu, 20 Aug 2026 17:45:07 -0400
Subject: [PATCH 7/7] Keep unresolved 1.0.81 regressions guarded
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---
go/internal/e2e/github_telemetry_e2e_test.go | 5 +
nodejs/test/e2e/permissions.e2e.test.ts | 131 ++++++++++---------
rust/tests/e2e/github_telemetry.rs | 5 +
3 files changed, 81 insertions(+), 60 deletions(-)
diff --git a/go/internal/e2e/github_telemetry_e2e_test.go b/go/internal/e2e/github_telemetry_e2e_test.go
index aa26ba31f2..6e1a36383f 100644
--- a/go/internal/e2e/github_telemetry_e2e_test.go
+++ b/go/internal/e2e/github_telemetry_e2e_test.go
@@ -12,6 +12,11 @@ import (
func TestGitHubTelemetryE2E(t *testing.T) {
t.Run("should forward github telemetry for a live session", func(t *testing.T) {
+ // TODO(cli-1.0.81-2): CLI 1.0.81-2 does not forward GitHub telemetry notifications
+ // over the in-process (FFI) host, mirroring the existing telemetry-configuration
+ // limitation. Still covered by the default (stdio) transport.
+ testharness.SkipIfInProcess(t, "GitHub telemetry forwarding is not honored in-process")
+
ctx := testharness.NewTestContext(t)
ctx.ConfigureForTest(t)
diff --git a/nodejs/test/e2e/permissions.e2e.test.ts b/nodejs/test/e2e/permissions.e2e.test.ts
index b7fa6087a3..d7600ed165 100644
--- a/nodejs/test/e2e/permissions.e2e.test.ts
+++ b/nodejs/test/e2e/permissions.e2e.test.ts
@@ -17,6 +17,8 @@ import { approveAll, defineTool, createAttributedPermissionResult } from "../../
import { createSdkTestContext, isInProcessTransport } from "./harness/sdkTestContext.js";
import { getFinalAssistantMessage, getNextEventOfType } from "./harness/sdkTestHelper.js";
+const isWindows = process.platform === "win32";
+
describe("Permission callbacks", async () => {
const { copilotClient: client, workDir } = await createSdkTestContext();
@@ -630,67 +632,76 @@ describe("Permission callbacks", async () => {
}
});
- it("should invoke permission location and folder trust rpc apis", async () => {
- const session = await client.createSession({ onPermissionRequest: approveAll });
- const locationDirectory = await createUniqueWorkDirectory(workDir, "permission-location");
- const trustedDirectory = await createUniqueWorkDirectory(workDir, "folder-trust");
- const commandIdentifier = `node-permission-location-${Date.now()}`;
- try {
- const resolved = await session.rpc.permissions.locations.resolve({
- workingDirectory: locationDirectory,
- });
- expect(resolved.locationType).toBe("dir");
- expectPathEqual(resolved.locationKey, locationDirectory);
-
- expect(
- (
- await session.rpc.permissions.locations.addToolApproval({
- locationKey: resolved.locationKey,
- approval: {
- kind: "commands",
- commandIdentifiers: [commandIdentifier],
- },
- })
- ).success
- ).toBe(true);
-
- const applied = await session.rpc.permissions.locations.apply({
- workingDirectory: locationDirectory,
- });
- expect(applied.locationType).toBe(resolved.locationType);
- expectPathEqual(applied.locationKey, resolved.locationKey);
- expect(applied.appliedRuleCount).toBeGreaterThanOrEqual(1);
- expect(
- applied.appliedRules.some(
- (rule) => rule.kind === "shell" && rule.argument === commandIdentifier
- )
- ).toBe(true);
-
- expect(
- (
- await session.rpc.permissions.folderTrust.isTrusted({
- path: trustedDirectory,
- })
- ).trusted
- ).toBe(false);
- expect(
- (
- await session.rpc.permissions.folderTrust.addTrusted({
- path: trustedDirectory,
- })
- ).success
- ).toBe(true);
- expect(
- (
- await session.rpc.permissions.folderTrust.isTrusted({
- path: trustedDirectory,
- })
- ).trusted
- ).toBe(true);
- } finally {
- await session.disconnect();
+ // TODO(cli-1.0.81-2): CLI 1.0.81-2 no longer matches the location key returned by
+ // permissions.locations.resolve when permissions.locations.apply re-resolves it on Windows,
+ // so appliedRuleCount comes back as 0. Still covered on Linux and macOS.
+ it.skipIf(isWindows)(
+ "should invoke permission location and folder trust rpc apis",
+ async () => {
+ const session = await client.createSession({ onPermissionRequest: approveAll });
+ const locationDirectory = await createUniqueWorkDirectory(
+ workDir,
+ "permission-location"
+ );
+ const trustedDirectory = await createUniqueWorkDirectory(workDir, "folder-trust");
+ const commandIdentifier = `node-permission-location-${Date.now()}`;
+ try {
+ const resolved = await session.rpc.permissions.locations.resolve({
+ workingDirectory: locationDirectory,
+ });
+ expect(resolved.locationType).toBe("dir");
+ expectPathEqual(resolved.locationKey, locationDirectory);
+
+ expect(
+ (
+ await session.rpc.permissions.locations.addToolApproval({
+ locationKey: resolved.locationKey,
+ approval: {
+ kind: "commands",
+ commandIdentifiers: [commandIdentifier],
+ },
+ })
+ ).success
+ ).toBe(true);
+
+ const applied = await session.rpc.permissions.locations.apply({
+ workingDirectory: locationDirectory,
+ });
+ expect(applied.locationType).toBe(resolved.locationType);
+ expectPathEqual(applied.locationKey, resolved.locationKey);
+ expect(applied.appliedRuleCount).toBeGreaterThanOrEqual(1);
+ expect(
+ applied.appliedRules.some(
+ (rule) => rule.kind === "shell" && rule.argument === commandIdentifier
+ )
+ ).toBe(true);
+
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.isTrusted({
+ path: trustedDirectory,
+ })
+ ).trusted
+ ).toBe(false);
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.addTrusted({
+ path: trustedDirectory,
+ })
+ ).success
+ ).toBe(true);
+ expect(
+ (
+ await session.rpc.permissions.folderTrust.isTrusted({
+ path: trustedDirectory,
+ })
+ ).trusted
+ ).toBe(true);
+ } finally {
+ await session.disconnect();
+ }
}
- });
+ );
});
async function createUniqueWorkDirectory(baseDir: string, prefix: string): Promise {
diff --git a/rust/tests/e2e/github_telemetry.rs b/rust/tests/e2e/github_telemetry.rs
index 2047ee34ff..02af0e2ae8 100644
--- a/rust/tests/e2e/github_telemetry.rs
+++ b/rust/tests/e2e/github_telemetry.rs
@@ -9,6 +9,11 @@ use super::support::{DEFAULT_TEST_TOKEN, with_e2e_context_no_snapshot};
#[tokio::test]
async fn should_forward_github_telemetry_on_session_create() {
+ // TODO(cli-1.0.81-2): CLI 1.0.81-2 does not forward GitHub telemetry notifications over
+ // the in-process (FFI) host, mirroring the existing telemetry-configuration limitation.
+ if super::support::skip_inprocess("GitHub telemetry forwarding is not honored in-process") {
+ return;
+ }
with_e2e_context_no_snapshot(|ctx| {
Box::pin(async move {
ctx.set_default_copilot_user();