From 3b86b6850a64b788048e23ec268fdbf2997c1871 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 29 Apr 2026 15:16:57 +0000
Subject: [PATCH 1/2] Update @github/copilot to 1.0.39
- Updated nodejs and test harness dependencies
- Re-ran code generators
- Formatted generated code
---
dotnet/src/Generated/SessionEvents.cs | 20 ++++++++
go/generated_session_events.go | 8 ++++
nodejs/package-lock.json | 56 +++++++++++-----------
nodejs/package.json | 2 +-
nodejs/samples/package-lock.json | 2 +-
nodejs/src/generated/session-events.ts | 16 +++++++
python/copilot/generated/session_events.py | 20 ++++++++
test/harness/package-lock.json | 56 +++++++++++-----------
test/harness/package.json | 2 +-
9 files changed, 123 insertions(+), 59 deletions(-)
diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs
index 102597330..fdbf80724 100644
--- a/dotnet/src/Generated/SessionEvents.cs
+++ b/dotnet/src/Generated/SessionEvents.cs
@@ -1227,6 +1227,16 @@ public partial class SessionRemoteSteerableChangedData
/// Error details for timeline display including message and optional diagnostic information.
public partial class SessionErrorData
{
+ /// Only set on `errorType: "rate_limit"`. When `true`, the runtime will follow this error with an `auto_mode_switch.requested` event (or silently switch if `continueOnAutoMode` is enabled). UI clients can use this flag to suppress duplicate rendering of the rate-limit error when they show their own auto-mode-switch prompt.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("eligibleForAutoSwitch")]
+ public bool? EligibleForAutoSwitch { get; set; }
+
+ /// Fine-grained error code from the upstream provider, when available. For `errorType: "rate_limit"`, this is one of the `RateLimitErrorCode` values (e.g., `"user_weekly_rate_limited"`, `"user_global_rate_limited"`, `"rate_limited"`, `"user_model_rate_limited"`, `"integration_rate_limited"`).
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("errorCode")]
+ public string? ErrorCode { get; set; }
+
/// Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "context_limit", "query").
[JsonPropertyName("errorType")]
public required string ErrorType { get; set; }
@@ -1321,6 +1331,11 @@ public partial class SessionWarningData
/// Model change details including previous and new model identifiers.
public partial class SessionModelChangeData
{
+ /// Reason the change happened, when not user-initiated. Currently `"rate_limit_auto_switch"` for changes triggered by the auto-mode-switch rate-limit recovery path. UI clients can use this to render contextual copy.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("cause")]
+ public string? Cause { get; set; }
+
/// Newly selected model identifier.
[JsonPropertyName("newModel")]
public required string NewModel { get; set; }
@@ -2669,6 +2684,11 @@ public partial class AutoModeSwitchRequestedData
/// Unique identifier for this request; used to respond via session.respondToAutoModeSwitch().
[JsonPropertyName("requestId")]
public required string RequestId { get; set; }
+
+ /// Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("retryAfterSeconds")]
+ public double? RetryAfterSeconds { get; set; }
}
/// Auto mode switch completion notification.
diff --git a/go/generated_session_events.go b/go/generated_session_events.go
index 19a376e7a..4c1e26d34 100644
--- a/go/generated_session_events.go
+++ b/go/generated_session_events.go
@@ -714,6 +714,8 @@ type AutoModeSwitchRequestedData struct {
ErrorCode *string `json:"errorCode,omitempty"`
// Unique identifier for this request; used to respond via session.respondToAutoModeSwitch()
RequestID string `json:"requestId"`
+ // Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt.
+ RetryAfterSeconds *float64 `json:"retryAfterSeconds,omitempty"`
}
func (*AutoModeSwitchRequestedData) sessionEventData() {}
@@ -866,6 +868,10 @@ func (*PendingMessagesModifiedData) sessionEventData() {}
// Error details for timeline display including message and optional diagnostic information
type SessionErrorData struct {
+ // Only set on `errorType: "rate_limit"`. When `true`, the runtime will follow this error with an `auto_mode_switch.requested` event (or silently switch if `continueOnAutoMode` is enabled). UI clients can use this flag to suppress duplicate rendering of the rate-limit error when they show their own auto-mode-switch prompt.
+ EligibleForAutoSwitch *bool `json:"eligibleForAutoSwitch,omitempty"`
+ // Fine-grained error code from the upstream provider, when available. For `errorType: "rate_limit"`, this is one of the `RateLimitErrorCode` values (e.g., `"user_weekly_rate_limited"`, `"user_global_rate_limited"`, `"rate_limited"`, `"user_model_rate_limited"`, `"integration_rate_limited"`).
+ ErrorCode *string `json:"errorCode,omitempty"`
// Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "context_limit", "query")
ErrorType string `json:"errorType"`
// Human-readable error message
@@ -1025,6 +1031,8 @@ func (*McpOauthCompletedData) sessionEventData() {}
// Model change details including previous and new model identifiers
type SessionModelChangeData struct {
+ // Reason the change happened, when not user-initiated. Currently `"rate_limit_auto_switch"` for changes triggered by the auto-mode-switch rate-limit recovery path. UI clients can use this to render contextual copy.
+ Cause *string `json:"cause,omitempty"`
// Newly selected model identifier
NewModel string `json:"newModel"`
// Model that was previously selected, if any
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index f2a929d73..a4e86d453 100644
--- a/nodejs/package-lock.json
+++ b/nodejs/package-lock.json
@@ -9,7 +9,7 @@
"version": "0.1.8",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.39-0",
+ "@github/copilot": "^1.0.39",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -663,26 +663,26 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.39-0.tgz",
- "integrity": "sha512-OuN6wGgUv0WQydOCUuhYRFwUwTkfktI9fGdSih+SKUE+nTZze8JBz8Sg68K0ZLlqdD0OcF0ac9wMAfunlutvsw==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.39.tgz",
+ "integrity": "sha512-AY0VPYf6QQm88wUcOav2B36iedWKBUaMegKRxxY2uIHESiU6HueEuQR/n7D3U2UdD0zLox3jFRjYbZAsr2CgkQ==",
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.39-0",
- "@github/copilot-darwin-x64": "1.0.39-0",
- "@github/copilot-linux-arm64": "1.0.39-0",
- "@github/copilot-linux-x64": "1.0.39-0",
- "@github/copilot-win32-arm64": "1.0.39-0",
- "@github/copilot-win32-x64": "1.0.39-0"
+ "@github/copilot-darwin-arm64": "1.0.39",
+ "@github/copilot-darwin-x64": "1.0.39",
+ "@github/copilot-linux-arm64": "1.0.39",
+ "@github/copilot-linux-x64": "1.0.39",
+ "@github/copilot-win32-arm64": "1.0.39",
+ "@github/copilot-win32-x64": "1.0.39"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.39-0.tgz",
- "integrity": "sha512-DquiC7DZo+OmP2AtQUW27FCBsMGLshX9MEedWczjDgQ5YK2iMwACQLMeULdURssXJWXjvQQZMTTo0wsow59lnA==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.39.tgz",
+ "integrity": "sha512-E8WfNL43NMzMTDDpCiYikaEmYCMAr6mz8LHrJtkaFuVXVkBr/q2NI3hAtwHFy8M11Fac/MeIe3/VEymWwwh3kw==",
"cpu": [
"arm64"
],
@@ -696,9 +696,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.39-0.tgz",
- "integrity": "sha512-NPjVkyl6QqYLGWlkqSiegcSUuI59RE3Qt4cOTALGG9TZmGYa0Z60o26LYrANkUyyerLl8MDI14oIgtl52nuBrQ==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.39.tgz",
+ "integrity": "sha512-0zbC4lDVX7l8Wvq+JSCMjO0xTN69nWLejTBCl3Ev5bP6P+/7wPURcUvZKoHEaXxOULQ3AGj0DwZNAsvvQkA/6Q==",
"cpu": [
"x64"
],
@@ -712,9 +712,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.39-0.tgz",
- "integrity": "sha512-Rv2EsthoR40FPn+afObJ+Jef0Lbpb3S6TAKNz+1MHv71hlVVxNKBVCGXVCKIehVgwE8rQGKz+pTy2+Gbprim9A==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.39.tgz",
+ "integrity": "sha512-x88FuByweJlHlAmUZXjq4JlmtqgoM57Fe7nXzQkGr2Y5wnc2EDydBzFYEOlYDSWozQreimaJIm0KEMAA5T8/Fg==",
"cpu": [
"arm64"
],
@@ -728,9 +728,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.39-0.tgz",
- "integrity": "sha512-7z8lmFLAVWRgZ7WoSEQsF2XAMeenWU5kgjljhbupDGV1yhW9Ycrx7RhB3cBtmyvmal+OzFjOpYlTiLi0Ul3kwA==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.39.tgz",
+ "integrity": "sha512-ssahg8r7a0VCsHVXPRmFFXx70xNAxaTM2SZfG7qPRfFB2OM8gHrW26F2oikTklDF6D+A2MfSAMpzJLBUZbPnhw==",
"cpu": [
"x64"
],
@@ -744,9 +744,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.39-0.tgz",
- "integrity": "sha512-HtPnEV+Mt1H1RF54NHQa4qagj7llYkCcnHmc8jzkj810DE8iU4aI2u5K2fmU9/z/hvF1+223bEXRnSKAinyjmw==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.39.tgz",
+ "integrity": "sha512-hhBWGZQIywbp6MBxlqMX2GSmHqtUAOGwpo9b0igscecL4i0kz89QNasC+mKiN+zFEHP6I8gggOu87XPI17Io8Q==",
"cpu": [
"arm64"
],
@@ -760,9 +760,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.39-0.tgz",
- "integrity": "sha512-N3Q5G6hDLKeiU+40mgdZk3Sk3b6/+pvNE3Tp5B8LK/Z3CvE2fQKYRXJx8iSDNtP48QwRqwHdrCGQVwDtEtSDAQ==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.39.tgz",
+ "integrity": "sha512-0ehlMtBiwKjmfEY3hVZggdn7qrmPMC8ueBQv/b+6UY3SMRS/M/1Y7xkOCwG84NvJsktdSsk3SlQnE2LbkTVpSA==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index 2c7b12e1f..a1ee9764f 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.39-0",
+ "@github/copilot": "^1.0.39",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index 0e97a2e36..c5b69b9d5 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,7 +18,7 @@
"version": "0.1.8",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.39-0",
+ "@github/copilot": "^1.0.39",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index ad541ea88..5340ad21d 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -471,6 +471,14 @@ export interface ErrorEvent {
* Error details for timeline display including message and optional diagnostic information
*/
export interface ErrorData {
+ /**
+ * Only set on `errorType: "rate_limit"`. When `true`, the runtime will follow this error with an `auto_mode_switch.requested` event (or silently switch if `continueOnAutoMode` is enabled). UI clients can use this flag to suppress duplicate rendering of the rate-limit error when they show their own auto-mode-switch prompt.
+ */
+ eligibleForAutoSwitch?: boolean;
+ /**
+ * Fine-grained error code from the upstream provider, when available. For `errorType: "rate_limit"`, this is one of the `RateLimitErrorCode` values (e.g., `"user_weekly_rate_limited"`, `"user_global_rate_limited"`, `"rate_limited"`, `"user_model_rate_limited"`, `"integration_rate_limited"`).
+ */
+ errorCode?: string;
/**
* Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "context_limit", "query")
*/
@@ -670,6 +678,10 @@ export interface ModelChangeEvent {
* Model change details including previous and new model identifiers
*/
export interface ModelChangeData {
+ /**
+ * Reason the change happened, when not user-initiated. Currently `"rate_limit_auto_switch"` for changes triggered by the auto-mode-switch rate-limit recovery path. UI clients can use this to render contextual copy.
+ */
+ cause?: string;
/**
* Newly selected model identifier
*/
@@ -4331,6 +4343,10 @@ export interface AutoModeSwitchRequestedData {
* Unique identifier for this request; used to respond via session.respondToAutoModeSwitch()
*/
requestId: string;
+ /**
+ * Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt.
+ */
+ retryAfterSeconds?: number;
}
export interface AutoModeSwitchCompletedEvent {
/**
diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py
index 32599fdc3..6fb5acf31 100644
--- a/python/copilot/generated/session_events.py
+++ b/python/copilot/generated/session_events.py
@@ -775,15 +775,18 @@ class AutoModeSwitchRequestedData:
"Auto mode switch request notification requiring user approval"
request_id: str
error_code: str | None = None
+ retry_after_seconds: float | None = None
@staticmethod
def from_dict(obj: Any) -> "AutoModeSwitchRequestedData":
assert isinstance(obj, dict)
request_id = from_str(obj.get("requestId"))
error_code = from_union([from_none, from_str], obj.get("errorCode"))
+ retry_after_seconds = from_union([from_none, from_float], obj.get("retryAfterSeconds"))
return AutoModeSwitchRequestedData(
request_id=request_id,
error_code=error_code,
+ retry_after_seconds=retry_after_seconds,
)
def to_dict(self) -> dict:
@@ -791,6 +794,8 @@ def to_dict(self) -> dict:
result["requestId"] = from_str(self.request_id)
if self.error_code is not None:
result["errorCode"] = from_union([from_none, from_str], self.error_code)
+ if self.retry_after_seconds is not None:
+ result["retryAfterSeconds"] = from_union([from_none, to_float], self.retry_after_seconds)
return result
@@ -2353,6 +2358,8 @@ class SessionErrorData:
"Error details for timeline display including message and optional diagnostic information"
error_type: str
message: str
+ eligible_for_auto_switch: bool | None = None
+ error_code: str | None = None
provider_call_id: str | None = None
stack: str | None = None
status_code: int | None = None
@@ -2363,6 +2370,8 @@ def from_dict(obj: Any) -> "SessionErrorData":
assert isinstance(obj, dict)
error_type = from_str(obj.get("errorType"))
message = from_str(obj.get("message"))
+ eligible_for_auto_switch = from_union([from_none, from_bool], obj.get("eligibleForAutoSwitch"))
+ error_code = from_union([from_none, from_str], obj.get("errorCode"))
provider_call_id = from_union([from_none, from_str], obj.get("providerCallId"))
stack = from_union([from_none, from_str], obj.get("stack"))
status_code = from_union([from_none, from_int], obj.get("statusCode"))
@@ -2370,6 +2379,8 @@ def from_dict(obj: Any) -> "SessionErrorData":
return SessionErrorData(
error_type=error_type,
message=message,
+ eligible_for_auto_switch=eligible_for_auto_switch,
+ error_code=error_code,
provider_call_id=provider_call_id,
stack=stack,
status_code=status_code,
@@ -2380,6 +2391,10 @@ def to_dict(self) -> dict:
result: dict = {}
result["errorType"] = from_str(self.error_type)
result["message"] = from_str(self.message)
+ if self.eligible_for_auto_switch is not None:
+ result["eligibleForAutoSwitch"] = from_union([from_none, from_bool], self.eligible_for_auto_switch)
+ if self.error_code is not None:
+ result["errorCode"] = from_union([from_none, from_str], self.error_code)
if self.provider_call_id is not None:
result["providerCallId"] = from_union([from_none, from_str], self.provider_call_id)
if self.stack is not None:
@@ -2577,6 +2592,7 @@ def to_dict(self) -> dict:
class SessionModelChangeData:
"Model change details including previous and new model identifiers"
new_model: str
+ cause: str | None = None
previous_model: str | None = None
previous_reasoning_effort: str | None = None
reasoning_effort: str | None = None
@@ -2585,11 +2601,13 @@ class SessionModelChangeData:
def from_dict(obj: Any) -> "SessionModelChangeData":
assert isinstance(obj, dict)
new_model = from_str(obj.get("newModel"))
+ cause = from_union([from_none, from_str], obj.get("cause"))
previous_model = from_union([from_none, from_str], obj.get("previousModel"))
previous_reasoning_effort = from_union([from_none, from_str], obj.get("previousReasoningEffort"))
reasoning_effort = from_union([from_none, from_str], obj.get("reasoningEffort"))
return SessionModelChangeData(
new_model=new_model,
+ cause=cause,
previous_model=previous_model,
previous_reasoning_effort=previous_reasoning_effort,
reasoning_effort=reasoning_effort,
@@ -2598,6 +2616,8 @@ def from_dict(obj: Any) -> "SessionModelChangeData":
def to_dict(self) -> dict:
result: dict = {}
result["newModel"] = from_str(self.new_model)
+ if self.cause is not None:
+ result["cause"] = from_union([from_none, from_str], self.cause)
if self.previous_model is not None:
result["previousModel"] = from_union([from_none, from_str], self.previous_model)
if self.previous_reasoning_effort is not None:
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index ea6f5be9c..a1cc404f5 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.39-0",
+ "@github/copilot": "^1.0.39",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",
@@ -462,27 +462,27 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.39-0.tgz",
- "integrity": "sha512-OuN6wGgUv0WQydOCUuhYRFwUwTkfktI9fGdSih+SKUE+nTZze8JBz8Sg68K0ZLlqdD0OcF0ac9wMAfunlutvsw==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.39.tgz",
+ "integrity": "sha512-AY0VPYf6QQm88wUcOav2B36iedWKBUaMegKRxxY2uIHESiU6HueEuQR/n7D3U2UdD0zLox3jFRjYbZAsr2CgkQ==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.39-0",
- "@github/copilot-darwin-x64": "1.0.39-0",
- "@github/copilot-linux-arm64": "1.0.39-0",
- "@github/copilot-linux-x64": "1.0.39-0",
- "@github/copilot-win32-arm64": "1.0.39-0",
- "@github/copilot-win32-x64": "1.0.39-0"
+ "@github/copilot-darwin-arm64": "1.0.39",
+ "@github/copilot-darwin-x64": "1.0.39",
+ "@github/copilot-linux-arm64": "1.0.39",
+ "@github/copilot-linux-x64": "1.0.39",
+ "@github/copilot-win32-arm64": "1.0.39",
+ "@github/copilot-win32-x64": "1.0.39"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.39-0.tgz",
- "integrity": "sha512-DquiC7DZo+OmP2AtQUW27FCBsMGLshX9MEedWczjDgQ5YK2iMwACQLMeULdURssXJWXjvQQZMTTo0wsow59lnA==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.39.tgz",
+ "integrity": "sha512-E8WfNL43NMzMTDDpCiYikaEmYCMAr6mz8LHrJtkaFuVXVkBr/q2NI3hAtwHFy8M11Fac/MeIe3/VEymWwwh3kw==",
"cpu": [
"arm64"
],
@@ -497,9 +497,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.39-0.tgz",
- "integrity": "sha512-NPjVkyl6QqYLGWlkqSiegcSUuI59RE3Qt4cOTALGG9TZmGYa0Z60o26LYrANkUyyerLl8MDI14oIgtl52nuBrQ==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.39.tgz",
+ "integrity": "sha512-0zbC4lDVX7l8Wvq+JSCMjO0xTN69nWLejTBCl3Ev5bP6P+/7wPURcUvZKoHEaXxOULQ3AGj0DwZNAsvvQkA/6Q==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.39-0.tgz",
- "integrity": "sha512-Rv2EsthoR40FPn+afObJ+Jef0Lbpb3S6TAKNz+1MHv71hlVVxNKBVCGXVCKIehVgwE8rQGKz+pTy2+Gbprim9A==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.39.tgz",
+ "integrity": "sha512-x88FuByweJlHlAmUZXjq4JlmtqgoM57Fe7nXzQkGr2Y5wnc2EDydBzFYEOlYDSWozQreimaJIm0KEMAA5T8/Fg==",
"cpu": [
"arm64"
],
@@ -531,9 +531,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.39-0.tgz",
- "integrity": "sha512-7z8lmFLAVWRgZ7WoSEQsF2XAMeenWU5kgjljhbupDGV1yhW9Ycrx7RhB3cBtmyvmal+OzFjOpYlTiLi0Ul3kwA==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.39.tgz",
+ "integrity": "sha512-ssahg8r7a0VCsHVXPRmFFXx70xNAxaTM2SZfG7qPRfFB2OM8gHrW26F2oikTklDF6D+A2MfSAMpzJLBUZbPnhw==",
"cpu": [
"x64"
],
@@ -548,9 +548,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.39-0.tgz",
- "integrity": "sha512-HtPnEV+Mt1H1RF54NHQa4qagj7llYkCcnHmc8jzkj810DE8iU4aI2u5K2fmU9/z/hvF1+223bEXRnSKAinyjmw==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.39.tgz",
+ "integrity": "sha512-hhBWGZQIywbp6MBxlqMX2GSmHqtUAOGwpo9b0igscecL4i0kz89QNasC+mKiN+zFEHP6I8gggOu87XPI17Io8Q==",
"cpu": [
"arm64"
],
@@ -565,9 +565,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.39-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.39-0.tgz",
- "integrity": "sha512-N3Q5G6hDLKeiU+40mgdZk3Sk3b6/+pvNE3Tp5B8LK/Z3CvE2fQKYRXJx8iSDNtP48QwRqwHdrCGQVwDtEtSDAQ==",
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.39.tgz",
+ "integrity": "sha512-0ehlMtBiwKjmfEY3hVZggdn7qrmPMC8ueBQv/b+6UY3SMRS/M/1Y7xkOCwG84NvJsktdSsk3SlQnE2LbkTVpSA==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index 6b0c60b4e..57b18baff 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -11,7 +11,7 @@
"test": "vitest run"
},
"devDependencies": {
- "@github/copilot": "^1.0.39-0",
+ "@github/copilot": "^1.0.39",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",
From c7e2cbb815548339ea8fa84511dbe171f4b0c0a6 Mon Sep 17 00:00:00 2001
From: Stephen Toub
Date: Wed, 29 Apr 2026 12:06:02 -0400
Subject: [PATCH 2/2] Fix flaky multi-client reject permission test
Mirror the synchronization pattern from the 'approve' sibling: capture a
PermissionCompletedEvent task on session2 before subscribing and sending,
then await it before asserting that client2 observed PermissionRequestedEvent.
Without this wait, client2's event subscription could be asserted before the
event had propagated, causing intermittent failures (observed on macOS CI).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/test/MultiClientTests.cs | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/dotnet/test/MultiClientTests.cs b/dotnet/test/MultiClientTests.cs
index e3cc3512b..f3b4186fc 100644
--- a/dotnet/test/MultiClientTests.cs
+++ b/dotnet/test/MultiClientTests.cs
@@ -220,6 +220,9 @@ public async Task One_Client_Rejects_Permission_And_Both_See_The_Result()
var client1Events = new ConcurrentBag();
var client2Events = new ConcurrentBag();
+ // Wait for PermissionCompletedEvent on client2 which may arrive slightly after session1 goes idle
+ var client2PermissionCompleted = TestHelper.GetNextEventOfTypeAsync(session2);
+
using var sub1 = session1.On(evt => client1Events.Add(evt));
using var sub2 = session2.On(evt => client2Events.Add(evt));
@@ -235,6 +238,8 @@ await session1.SendAndWaitAsync(new MessageOptions
var content = await File.ReadAllTextAsync(Path.Combine(Ctx.WorkDir, "protected.txt"));
Assert.Equal("protected content", content);
+ await client2PermissionCompleted;
+
Assert.Contains(client1Events, e => e is PermissionRequestedEvent);
Assert.Contains(client2Events, e => e is PermissionRequestedEvent);