From ac552877ca8decac4dbdf4f495df616eed7d1d2e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 3 Apr 2026 17:40:08 +0000
Subject: [PATCH 1/2] Update @github/copilot to 1.0.17
- Updated nodejs and test harness dependencies
- Re-ran code generators
- Formatted generated code
---
dotnet/src/Generated/SessionEvents.cs | 15 +++++-
go/generated_session_events.go | 8 +++-
go/rpc/generated_rpc.go | 12 +++--
nodejs/package-lock.json | 56 +++++++++++-----------
nodejs/package.json | 2 +-
nodejs/samples/package-lock.json | 3 +-
nodejs/src/generated/rpc.ts | 5 ++
nodejs/src/generated/session-events.ts | 13 ++++-
python/copilot/generated/rpc.py | 7 ++-
python/copilot/generated/session_events.py | 20 ++++++--
test/harness/package-lock.json | 56 +++++++++++-----------
test/harness/package.json | 2 +-
12 files changed, 127 insertions(+), 72 deletions(-)
diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs
index c01d1ddcd..8b5c0a5f1 100644
--- a/dotnet/src/Generated/SessionEvents.cs
+++ b/dotnet/src/Generated/SessionEvents.cs
@@ -1180,7 +1180,7 @@ public partial class SessionRemoteSteerableChangedData
/// Error details for timeline display including message and optional diagnostic information.
public partial class SessionErrorData
{
- /// Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "query").
+ /// Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "context_limit", "query").
[JsonPropertyName("errorType")]
public required string ErrorType { get; set; }
@@ -2267,6 +2267,11 @@ public partial class PermissionRequestedData
/// Details of the permission being requested.
[JsonPropertyName("permissionRequest")]
public required PermissionRequest PermissionRequest { get; set; }
+
+ /// When true, this permission was already resolved by a permissionRequest hook and requires no client action.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("resolvedByHook")]
+ public bool? ResolvedByHook { get; set; }
}
/// Permission request completion notification signaling UI dismissal.
@@ -2998,6 +3003,11 @@ public partial class AssistantMessageDataToolRequestsItem
[JsonPropertyName("toolTitle")]
public string? ToolTitle { get; set; }
+ /// Name of the MCP server hosting this tool, when the tool is an MCP tool.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("mcpServerName")]
+ public string? McpServerName { get; set; }
+
/// Resolved intention summary describing what this specific call does.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("intentionSummary")]
@@ -3989,6 +3999,9 @@ public enum PermissionCompletedDataResultKind
/// The denied-by-content-exclusion-policy variant.
[JsonStringEnumMemberName("denied-by-content-exclusion-policy")]
DeniedByContentExclusionPolicy,
+ /// The denied-by-permission-request-hook variant.
+ [JsonStringEnumMemberName("denied-by-permission-request-hook")]
+ DeniedByPermissionRequestHook,
}
/// Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent.
diff --git a/go/generated_session_events.go b/go/generated_session_events.go
index 4799aca91..e3b6fa71e 100644
--- a/go/generated_session_events.go
+++ b/go/generated_session_events.go
@@ -358,7 +358,7 @@ type Data struct {
// ISO 8601 timestamp when the session was resumed
ResumeTime *time.Time `json:"resumeTime,omitempty"`
// Category of error (e.g., "authentication", "authorization", "quota", "rate_limit",
- // "query")
+ // "context_limit", "query")
ErrorType *string `json:"errorType,omitempty"`
// Human-readable error message
//
@@ -801,6 +801,9 @@ type Data struct {
Kind *KindClass `json:"kind,omitempty"`
// Details of the permission being requested
PermissionRequest *PermissionRequest `json:"permissionRequest,omitempty"`
+ // When true, this permission was already resolved by a permissionRequest hook and requires
+ // no client action
+ ResolvedByHook *bool `json:"resolvedByHook,omitempty"`
// Whether the user can provide a free-form text response in addition to predefined choices
AllowFreeform *bool `json:"allowFreeform,omitempty"`
// Predefined choices for the user to select from, if applicable
@@ -1403,6 +1406,8 @@ type ToolRequest struct {
Arguments interface{} `json:"arguments"`
// Resolved intention summary describing what this specific call does
IntentionSummary *string `json:"intentionSummary"`
+ // Name of the MCP server hosting this tool, when the tool is an MCP tool
+ MCPServerName *string `json:"mcpServerName,omitempty"`
// Name of the tool being invoked
Name string `json:"name"`
// Unique identifier for this tool call
@@ -1556,6 +1561,7 @@ type ResultKind string
const (
ResultKindApproved ResultKind = "approved"
ResultKindDeniedByContentExclusionPolicy ResultKind = "denied-by-content-exclusion-policy"
+ ResultKindDeniedByPermissionRequestHook ResultKind = "denied-by-permission-request-hook"
ResultKindDeniedByRules ResultKind = "denied-by-rules"
ResultKindDeniedInteractivelyByUser ResultKind = "denied-interactively-by-user"
ResultKindDeniedNoApprovalRuleAndCouldNotRequestFromUser ResultKind = "denied-no-approval-rule-and-could-not-request-from-user"
diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go
index f6011d900..3e7b336b7 100644
--- a/go/rpc/generated_rpc.go
+++ b/go/rpc/generated_rpc.go
@@ -652,11 +652,12 @@ type SessionPermissionsHandlePendingPermissionRequestParams struct {
}
type SessionPermissionsHandlePendingPermissionRequestParamsResult struct {
- Kind Kind `json:"kind"`
- Rules []any `json:"rules,omitempty"`
- Feedback *string `json:"feedback,omitempty"`
- Message *string `json:"message,omitempty"`
- Path *string `json:"path,omitempty"`
+ Kind Kind `json:"kind"`
+ Rules []any `json:"rules,omitempty"`
+ Feedback *string `json:"feedback,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Path *string `json:"path,omitempty"`
+ Interrupt *bool `json:"interrupt,omitempty"`
}
type SessionLogResult struct {
@@ -815,6 +816,7 @@ type Kind string
const (
KindApproved Kind = "approved"
KindDeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy"
+ KindDeniedByPermissionRequestHook Kind = "denied-by-permission-request-hook"
KindDeniedByRules Kind = "denied-by-rules"
KindDeniedInteractivelyByUser Kind = "denied-interactively-by-user"
KindDeniedNoApprovalRuleAndCouldNotRequestFromUser Kind = "denied-no-approval-rule-and-could-not-request-from-user"
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index 1af6e76c6..98ed1f0c7 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.15-2",
+ "@github/copilot": "^1.0.17",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -663,26 +663,26 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.15-2.tgz",
- "integrity": "sha512-ZVwGAH9u55CbGsM2fbZr9yL7oML5NZxfMbATBU9hWY8yEjiaSj+9WkRPxCSxGsd2cu4tw3OcHhFkDvxvWd2QpQ==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.17.tgz",
+ "integrity": "sha512-RTJ+kEKOdidjuOs8ozsoBdz+94g7tFJIEu5kz1P2iwJhsL+iIA5rtn9/jXOF0hAI3CLSXKZoSd66cqHrn4rb1A==",
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.15-2",
- "@github/copilot-darwin-x64": "1.0.15-2",
- "@github/copilot-linux-arm64": "1.0.15-2",
- "@github/copilot-linux-x64": "1.0.15-2",
- "@github/copilot-win32-arm64": "1.0.15-2",
- "@github/copilot-win32-x64": "1.0.15-2"
+ "@github/copilot-darwin-arm64": "1.0.17",
+ "@github/copilot-darwin-x64": "1.0.17",
+ "@github/copilot-linux-arm64": "1.0.17",
+ "@github/copilot-linux-x64": "1.0.17",
+ "@github/copilot-win32-arm64": "1.0.17",
+ "@github/copilot-win32-x64": "1.0.17"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.15-2.tgz",
- "integrity": "sha512-J2kvPBbNC636z3YdFdg2uK8YAF0o1ktss4Cmz+WVi5+5rNzscty3GmUoWBgw1AtPRNSeFT8amMVZ9xBvkpzA/A==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.17.tgz",
+ "integrity": "sha512-LSv66P8611y/UjTESnaHLYqLl9kA9yBYsaocZPQoOsvMgCmktgaBgUWq+KMpLMicaFN0jBAE5F0Ve7dW6N9X3A==",
"cpu": [
"arm64"
],
@@ -696,9 +696,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.15-2.tgz",
- "integrity": "sha512-utoHP7RyJXasNVQtpAhkDfp4jTLiNwJf5ZFjOkb9XMASre0+i4CfsokuXb1yPXczXFnrLcreVWQ2wtSuRiyV3A==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.17.tgz",
+ "integrity": "sha512-yqRS0/8kYTGl4VvfJ/QOtHTeYF+DnAWNUReZgt2U0AEP3zgj4z4hxSH7D2PsO/488L4KsBmmcnJr13HmBGiT/w==",
"cpu": [
"x64"
],
@@ -712,9 +712,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.15-2.tgz",
- "integrity": "sha512-tkqt6W+3VhZRvTMQoNj80s5JWNu5TXPYnNQkrPzAviqTsd8BRXOSGnqcIL7DvU+Y0z4pY5IS0ZECByB0IsRSHw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.17.tgz",
+ "integrity": "sha512-TOK0ma0A24zmQJslkGxUk+KnMFpiqquWEXB5sIv/5Ci45Qi7s0BRWTnqtiJ8Vahwb/wkja6KarHkLA27+ETGUA==",
"cpu": [
"arm64"
],
@@ -728,9 +728,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.15-2.tgz",
- "integrity": "sha512-svGfox/x8pNzrxcTAkpbqyWzaeQiJaRj6ZuQzzGJGi5+G6kAok3iqIInO+QYNB6fozW8oLnR8QJigAoj8Ldzbw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.17.tgz",
+ "integrity": "sha512-4Yum3uaAuTM/SiNtzchsO/G/144Bi/Z4FEcearW6WsGDvS6cRwSJeudOM0y4aoy4BHcv8+yw7YuXH5BHC3SAiA==",
"cpu": [
"x64"
],
@@ -744,9 +744,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.15-2.tgz",
- "integrity": "sha512-ZM/cmICtOOknMLkN42OvCRaLp5qJPBN9GAKkwTWCrhBmFpAIjC9O679AQA6KiCNj4OUzL6Hi5mSl9ufdUzPwkw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.17.tgz",
+ "integrity": "sha512-I1ferbfQ0aS149WyEUw6XS1sFixwTUUm13BPBQ3yMzD8G2SaoxTsdYdlhZpkVfkfh/rUYyvMKKi9VNxoVYOlDA==",
"cpu": [
"arm64"
],
@@ -760,9 +760,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.15-2",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.15-2.tgz",
- "integrity": "sha512-tAyd3Fzta6XJoH5MZ3yaw4H8i92C6k0zVkLKzL5zhrm4YEGWyQMcGB7NlLcvcmKewx49smCjbWtO/TIcVWJrrA==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.17.tgz",
+ "integrity": "sha512-kjiOxY9ibS+rPp9XFpPdfdYzluEL3SHN8R5/fnA7RO+kZEJ4FDKWJjAiec3tgVkEHQT3UwNuVa/u3TdfYNF15w==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index ce8d99a86..99681ec3f 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.15-2",
+ "@github/copilot": "^1.0.17",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json
index cd2ce2305..c0749ee6c 100644
--- a/nodejs/samples/package-lock.json
+++ b/nodejs/samples/package-lock.json
@@ -18,11 +18,12 @@
"version": "0.1.8",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.11",
+ "@github/copilot": "^1.0.17",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
"devDependencies": {
+ "@platformatic/vfs": "^0.3.0",
"@types/node": "^25.2.0",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.54.0",
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index 845d49129..4f87c14f2 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -1185,6 +1185,11 @@ export interface SessionPermissionsHandlePendingPermissionRequestParams {
kind: "denied-by-content-exclusion-policy";
path: string;
message: string;
+ }
+ | {
+ kind: "denied-by-permission-request-hook";
+ message?: string;
+ interrupt?: boolean;
};
}
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index 137c474f2..642c933cd 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -229,7 +229,7 @@ export type SessionEvent =
*/
data: {
/**
- * Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "query")
+ * Category of error (e.g., "authentication", "authorization", "quota", "rate_limit", "context_limit", "query")
*/
errorType: string;
/**
@@ -1480,6 +1480,10 @@ export type SessionEvent =
* Human-readable display title for the tool
*/
toolTitle?: string;
+ /**
+ * Name of the MCP server hosting this tool, when the tool is an MCP tool
+ */
+ mcpServerName?: string;
/**
* Resolved intention summary describing what this specific call does
*/
@@ -2872,6 +2876,10 @@ export type SessionEvent =
*/
hookMessage?: string;
};
+ /**
+ * When true, this permission was already resolved by a permissionRequest hook and requires no client action
+ */
+ resolvedByHook?: boolean;
};
}
| {
@@ -2909,7 +2917,8 @@ export type SessionEvent =
| "denied-by-rules"
| "denied-no-approval-rule-and-could-not-request-from-user"
| "denied-interactively-by-user"
- | "denied-by-content-exclusion-policy";
+ | "denied-by-content-exclusion-policy"
+ | "denied-by-permission-request-hook";
};
};
}
diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py
index 39e20a05d..7852d9984 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -2257,6 +2257,7 @@ def to_dict(self) -> dict:
class Kind(Enum):
APPROVED = "approved"
DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy"
+ DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook"
DENIED_BY_RULES = "denied-by-rules"
DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user"
DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user"
@@ -2269,6 +2270,7 @@ class SessionPermissionsHandlePendingPermissionRequestParamsResult:
feedback: str | None = None
message: str | None = None
path: str | None = None
+ interrupt: bool | None = None
@staticmethod
def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestParamsResult':
@@ -2278,7 +2280,8 @@ def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestPara
feedback = from_union([from_str, from_none], obj.get("feedback"))
message = from_union([from_str, from_none], obj.get("message"))
path = from_union([from_str, from_none], obj.get("path"))
- return SessionPermissionsHandlePendingPermissionRequestParamsResult(kind, rules, feedback, message, path)
+ interrupt = from_union([from_bool, from_none], obj.get("interrupt"))
+ return SessionPermissionsHandlePendingPermissionRequestParamsResult(kind, rules, feedback, message, path, interrupt)
def to_dict(self) -> dict:
result: dict = {}
@@ -2291,6 +2294,8 @@ def to_dict(self) -> dict:
result["message"] = from_union([from_str, from_none], self.message)
if self.path is not None:
result["path"] = from_union([from_str, from_none], self.path)
+ if self.interrupt is not None:
+ result["interrupt"] = from_union([from_bool, from_none], self.interrupt)
return result
diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py
index 2c3acba81..9b4267829 100644
--- a/python/copilot/generated/session_events.py
+++ b/python/copilot/generated/session_events.py
@@ -1500,6 +1500,7 @@ class ResultKind(Enum):
APPROVED = "approved"
DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy"
+ DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook"
DENIED_BY_RULES = "denied-by-rules"
DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user"
DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user"
@@ -1708,6 +1709,9 @@ class ToolRequest:
intention_summary: str | None = None
"""Resolved intention summary describing what this specific call does"""
+ mcp_server_name: str | None = None
+ """Name of the MCP server hosting this tool, when the tool is an MCP tool"""
+
tool_title: str | None = None
"""Human-readable display title for the tool"""
@@ -1723,9 +1727,10 @@ def from_dict(obj: Any) -> 'ToolRequest':
tool_call_id = from_str(obj.get("toolCallId"))
arguments = obj.get("arguments")
intention_summary = from_union([from_none, from_str], obj.get("intentionSummary"))
+ mcp_server_name = from_union([from_str, from_none], obj.get("mcpServerName"))
tool_title = from_union([from_str, from_none], obj.get("toolTitle"))
type = from_union([ToolRequestType, from_none], obj.get("type"))
- return ToolRequest(name, tool_call_id, arguments, intention_summary, tool_title, type)
+ return ToolRequest(name, tool_call_id, arguments, intention_summary, mcp_server_name, tool_title, type)
def to_dict(self) -> dict:
result: dict = {}
@@ -1735,6 +1740,8 @@ def to_dict(self) -> dict:
result["arguments"] = self.arguments
if self.intention_summary is not None:
result["intentionSummary"] = from_union([from_none, from_str], self.intention_summary)
+ if self.mcp_server_name is not None:
+ result["mcpServerName"] = from_union([from_str, from_none], self.mcp_server_name)
if self.tool_title is not None:
result["toolTitle"] = from_union([from_str, from_none], self.tool_title)
if self.type is not None:
@@ -1957,7 +1964,7 @@ class Data:
error_type: str | None = None
"""Category of error (e.g., "authentication", "authorization", "quota", "rate_limit",
- "query")
+ "context_limit", "query")
"""
message: str | None = None
"""Human-readable error message
@@ -2527,6 +2534,10 @@ class Data:
permission_request: PermissionRequest | None = None
"""Details of the permission being requested"""
+ resolved_by_hook: bool | None = None
+ """When true, this permission was already resolved by a permissionRequest hook and requires
+ no client action
+ """
allow_freeform: bool | None = None
"""Whether the user can provide a free-form text response in addition to predefined choices"""
@@ -2758,6 +2769,7 @@ def from_dict(obj: Any) -> 'Data':
role = from_union([Role, from_none], obj.get("role"))
kind = from_union([KindClass.from_dict, from_none], obj.get("kind"))
permission_request = from_union([PermissionRequest.from_dict, from_none], obj.get("permissionRequest"))
+ resolved_by_hook = from_union([from_bool, from_none], obj.get("resolvedByHook"))
allow_freeform = from_union([from_bool, from_none], obj.get("allowFreeform"))
choices = from_union([lambda x: from_list(from_str, x), from_none], obj.get("choices"))
question = from_union([from_str, from_none], obj.get("question"))
@@ -2785,7 +2797,7 @@ def from_dict(obj: Any) -> 'Data':
servers = from_union([lambda x: from_list(Server.from_dict, x), from_none], obj.get("servers"))
status = from_union([ServerStatus, from_none], obj.get("status"))
extensions = from_union([lambda x: from_list(Extension.from_dict, x), from_none], obj.get("extensions"))
- return Data(already_in_use, context, copilot_version, producer, reasoning_effort, remote_steerable, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, provider_call_id, stack, status_code, url, aborted, background_tasks, title, info_type, warning_type, new_model, previous_model, previous_reasoning_effort, new_mode, previous_mode, operation, path, handoff_time, host, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, events_removed, up_to_event_id, code_changes, conversation_tokens, current_model, current_tokens, error_reason, model_metrics, session_start_time, shutdown_type, system_tokens, tool_definitions_tokens, total_api_duration_ms, total_premium_requests, base_commit, branch, cwd, git_root, head_commit, host_type, is_initial, messages_length, checkpoint_number, checkpoint_path, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, request_id, success, summary_content, tokens_removed, agent_mode, attachments, content, interaction_id, source, transformed_content, turn_id, intent, reasoning_id, delta_content, total_response_size_bytes, encrypted_content, message_id, output_tokens, parent_tool_call_id, phase, reasoning_opaque, reasoning_text, tool_requests, api_call_id, cache_read_tokens, cache_write_tokens, copilot_usage, cost, duration, initiator, input_tokens, inter_token_latency_ms, model, quota_snapshots, ttft_ms, reason, arguments, tool_call_id, tool_name, mcp_server_name, mcp_tool_name, partial_output, progress_message, is_user_requested, result, tool_telemetry, allowed_tools, description, name, plugin_name, plugin_version, agent_description, agent_display_name, agent_name, duration_ms, total_tokens, total_tool_calls, tools, hook_invocation_id, hook_type, input, output, metadata, role, kind, permission_request, allow_freeform, choices, question, elicitation_source, mode, requested_schema, mcp_request_id, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, ui, actions, plan_content, recommended_action, skills, agents, errors, warnings, servers, status, extensions)
+ return Data(already_in_use, context, copilot_version, producer, reasoning_effort, remote_steerable, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, provider_call_id, stack, status_code, url, aborted, background_tasks, title, info_type, warning_type, new_model, previous_model, previous_reasoning_effort, new_mode, previous_mode, operation, path, handoff_time, host, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, events_removed, up_to_event_id, code_changes, conversation_tokens, current_model, current_tokens, error_reason, model_metrics, session_start_time, shutdown_type, system_tokens, tool_definitions_tokens, total_api_duration_ms, total_premium_requests, base_commit, branch, cwd, git_root, head_commit, host_type, is_initial, messages_length, checkpoint_number, checkpoint_path, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, request_id, success, summary_content, tokens_removed, agent_mode, attachments, content, interaction_id, source, transformed_content, turn_id, intent, reasoning_id, delta_content, total_response_size_bytes, encrypted_content, message_id, output_tokens, parent_tool_call_id, phase, reasoning_opaque, reasoning_text, tool_requests, api_call_id, cache_read_tokens, cache_write_tokens, copilot_usage, cost, duration, initiator, input_tokens, inter_token_latency_ms, model, quota_snapshots, ttft_ms, reason, arguments, tool_call_id, tool_name, mcp_server_name, mcp_tool_name, partial_output, progress_message, is_user_requested, result, tool_telemetry, allowed_tools, description, name, plugin_name, plugin_version, agent_description, agent_display_name, agent_name, duration_ms, total_tokens, total_tool_calls, tools, hook_invocation_id, hook_type, input, output, metadata, role, kind, permission_request, resolved_by_hook, allow_freeform, choices, question, elicitation_source, mode, requested_schema, mcp_request_id, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, ui, actions, plan_content, recommended_action, skills, agents, errors, warnings, servers, status, extensions)
def to_dict(self) -> dict:
result: dict = {}
@@ -3069,6 +3081,8 @@ def to_dict(self) -> dict:
result["kind"] = from_union([lambda x: to_class(KindClass, x), from_none], self.kind)
if self.permission_request is not None:
result["permissionRequest"] = from_union([lambda x: to_class(PermissionRequest, x), from_none], self.permission_request)
+ if self.resolved_by_hook is not None:
+ result["resolvedByHook"] = from_union([from_bool, from_none], self.resolved_by_hook)
if self.allow_freeform is not None:
result["allowFreeform"] = from_union([from_bool, from_none], self.allow_freeform)
if self.choices is not None:
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index d1ee2fa24..5d055e680 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.14-0",
+ "@github/copilot": "^1.0.17",
"@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.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.14-0.tgz",
- "integrity": "sha512-9eA5sFbvx69OtQnVoeik/8boFqHgGAhylLeUjEACc3kB70aaH1E/cHgxNzSMyYgZDjpXov0/IBXjtx2otpfHBw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.17.tgz",
+ "integrity": "sha512-RTJ+kEKOdidjuOs8ozsoBdz+94g7tFJIEu5kz1P2iwJhsL+iIA5rtn9/jXOF0hAI3CLSXKZoSd66cqHrn4rb1A==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.14-0",
- "@github/copilot-darwin-x64": "1.0.14-0",
- "@github/copilot-linux-arm64": "1.0.14-0",
- "@github/copilot-linux-x64": "1.0.14-0",
- "@github/copilot-win32-arm64": "1.0.14-0",
- "@github/copilot-win32-x64": "1.0.14-0"
+ "@github/copilot-darwin-arm64": "1.0.17",
+ "@github/copilot-darwin-x64": "1.0.17",
+ "@github/copilot-linux-arm64": "1.0.17",
+ "@github/copilot-linux-x64": "1.0.17",
+ "@github/copilot-win32-arm64": "1.0.17",
+ "@github/copilot-win32-x64": "1.0.17"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.14-0.tgz",
- "integrity": "sha512-w11Eqmfnu0ihrvgLysTd5Tkq8LuQa9eW63CNTQ/k5copnG1AMCdvd3K/78MxE2DdFJPq2L95KGS5cs9jH1dlIw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.17.tgz",
+ "integrity": "sha512-LSv66P8611y/UjTESnaHLYqLl9kA9yBYsaocZPQoOsvMgCmktgaBgUWq+KMpLMicaFN0jBAE5F0Ve7dW6N9X3A==",
"cpu": [
"arm64"
],
@@ -497,9 +497,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.14-0.tgz",
- "integrity": "sha512-4X/dMSPxCE/rvL6N1tgnwFxBg2uXnPrN63GGgS/FqK/fNi3TtcuojDVv8K1yjmEYpF8PXdkQttDlp6bKc+Nonw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.17.tgz",
+ "integrity": "sha512-yqRS0/8kYTGl4VvfJ/QOtHTeYF+DnAWNUReZgt2U0AEP3zgj4z4hxSH7D2PsO/488L4KsBmmcnJr13HmBGiT/w==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.14-0.tgz",
- "integrity": "sha512-A4thcLUoErEvfBO3Hsl/hJASibn44qwZm1ZSeVBPCa1FkpowBwo8fT1eV9EwN/ftKsyks3QkndNFvHkVzjUfxA==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.17.tgz",
+ "integrity": "sha512-TOK0ma0A24zmQJslkGxUk+KnMFpiqquWEXB5sIv/5Ci45Qi7s0BRWTnqtiJ8Vahwb/wkja6KarHkLA27+ETGUA==",
"cpu": [
"arm64"
],
@@ -531,9 +531,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.14-0.tgz",
- "integrity": "sha512-Kwn+Qn8/BqWRKa2DewZipH7rPIO8nDRWzpVy/ZLcRWBAvnIU+6BLWfhnYEU44DsqkD2VeWhKVfQlNmDX23xKKg==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.17.tgz",
+ "integrity": "sha512-4Yum3uaAuTM/SiNtzchsO/G/144Bi/Z4FEcearW6WsGDvS6cRwSJeudOM0y4aoy4BHcv8+yw7YuXH5BHC3SAiA==",
"cpu": [
"x64"
],
@@ -548,9 +548,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.14-0.tgz",
- "integrity": "sha512-8P5kxcb8YVWSS+Ihs+ykyy8jov1WwQ8GKV4d7mJN268Jpd8y5VI8Peb7uE2VO0lRLgq5c2VcXuZDsLG/1Wgnlw==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.17.tgz",
+ "integrity": "sha512-I1ferbfQ0aS149WyEUw6XS1sFixwTUUm13BPBQ3yMzD8G2SaoxTsdYdlhZpkVfkfh/rUYyvMKKi9VNxoVYOlDA==",
"cpu": [
"arm64"
],
@@ -565,9 +565,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.14-0",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.14-0.tgz",
- "integrity": "sha512-JWxp08j5o/PUkRZtZVagNYJLjH+KCURCyZRb7BfnC0A3vLeqcJQ70JC5qlYEAlcRnb4uCUJnmnpbWLLOJ+ObrA==",
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.17.tgz",
+ "integrity": "sha512-kjiOxY9ibS+rPp9XFpPdfdYzluEL3SHN8R5/fnA7RO+kZEJ4FDKWJjAiec3tgVkEHQT3UwNuVa/u3TdfYNF15w==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index f8fe732e4..257caf35c 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -11,7 +11,7 @@
"test": "vitest run"
},
"devDependencies": {
- "@github/copilot": "^1.0.14-0",
+ "@github/copilot": "^1.0.17",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",
From 8638ca6dabee86fb76a36cc3b4fb91d1f0e4c92c Mon Sep 17 00:00:00 2001
From: Mackinnon Buck
Date: Fri, 3 Apr 2026 11:19:34 -0700
Subject: [PATCH 2/2] Skip permission RPC response when resolvedByHook is true
When the runtime resolves a permission request via a permissionRequest
hook, it sets resolvedByHook=true on the broadcast event. The SDK
broadcast handlers were unconditionally invoking the permission handler
and sending an RPC response, causing duplicate/invalid responses.
Add a guard in all four SDKs (Node, Python, Go, .NET) to skip the
permission handler and RPC response when resolvedByHook is set, while
still allowing event subscribers to observe the event.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/src/Session.cs | 3 +++
go/session.go | 3 +++
nodejs/src/session.ts | 6 +++++-
python/copilot/session.py | 4 ++++
4 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs
index ae3d0c85b..3468e9b52 100644
--- a/dotnet/src/Session.cs
+++ b/dotnet/src/Session.cs
@@ -456,6 +456,9 @@ private async Task HandleBroadcastEventAsync(SessionEvent sessionEvent)
if (string.IsNullOrEmpty(data.RequestId) || data.PermissionRequest is null)
return;
+ if (data.ResolvedByHook == true)
+ return; // Already resolved by a permissionRequest hook; no client action needed.
+
var handler = _permissionHandler;
if (handler is null)
return; // This client doesn't handle permissions; another client will.
diff --git a/go/session.go b/go/session.go
index 04c1a05b0..225f2bf5e 100644
--- a/go/session.go
+++ b/go/session.go
@@ -915,6 +915,9 @@ func (s *Session) handleBroadcastEvent(event SessionEvent) {
if requestID == nil || event.Data.PermissionRequest == nil {
return
}
+ if event.Data.ResolvedByHook != nil && *event.Data.ResolvedByHook {
+ return // Already resolved by a permissionRequest hook; no client action needed.
+ }
handler := s.getPermissionHandler()
if handler == nil {
return
diff --git a/nodejs/src/session.ts b/nodejs/src/session.ts
index 50f094e5a..0bd5ad7b8 100644
--- a/nodejs/src/session.ts
+++ b/nodejs/src/session.ts
@@ -408,10 +408,14 @@ export class CopilotSession {
);
}
} else if (event.type === "permission.requested") {
- const { requestId, permissionRequest } = event.data as {
+ const { requestId, permissionRequest, resolvedByHook } = event.data as {
requestId: string;
permissionRequest: PermissionRequest;
+ resolvedByHook?: boolean;
};
+ if (resolvedByHook) {
+ return; // Already resolved by a permissionRequest hook; no client action needed.
+ }
if (this.permissionHandler) {
void this._executePermissionAndRespond(requestId, permissionRequest);
}
diff --git a/python/copilot/session.py b/python/copilot/session.py
index 96bb4730b..9bf384fbe 100644
--- a/python/copilot/session.py
+++ b/python/copilot/session.py
@@ -1224,6 +1224,10 @@ def _handle_broadcast_event(self, event: SessionEvent) -> None:
if not request_id or not permission_request:
return
+ resolved_by_hook = getattr(event.data, "resolved_by_hook", None)
+ if resolved_by_hook:
+ return # Already resolved by a permissionRequest hook; no client action needed.
+
with self._permission_handler_lock:
perm_handler = self._permission_handler
if not perm_handler: