From ae48ce3e3261892da4c49a0821a249f5a63c2c7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:22:45 +0000 Subject: [PATCH] Update @github/copilot to 1.0.11 - Updated nodejs and test harness dependencies - Re-ran code generators - Formatted generated code --- dotnet/src/Generated/SessionEvents.cs | 114 ++++++++++++++ go/generated_session_events.go | 46 +++++- nodejs/package-lock.json | 56 +++---- nodejs/package.json | 2 +- nodejs/samples/package-lock.json | 2 +- nodejs/src/generated/session-events.ts | 99 +++++++++++++ python/copilot/generated/session_events.py | 165 +++++++++++++++++---- test/harness/package-lock.json | 56 +++---- test/harness/package.json | 2 +- 9 files changed, 450 insertions(+), 92 deletions(-) diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index d5ef13d53..48a694a37 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -49,6 +49,7 @@ namespace GitHub.Copilot.SDK; [JsonDerivedType(typeof(SessionCompactionCompleteEvent), "session.compaction_complete")] [JsonDerivedType(typeof(SessionCompactionStartEvent), "session.compaction_start")] [JsonDerivedType(typeof(SessionContextChangedEvent), "session.context_changed")] +[JsonDerivedType(typeof(SessionCustomAgentsUpdatedEvent), "session.custom_agents_updated")] [JsonDerivedType(typeof(SessionErrorEvent), "session.error")] [JsonDerivedType(typeof(SessionExtensionsLoadedEvent), "session.extensions_loaded")] [JsonDerivedType(typeof(SessionHandoffEvent), "session.handoff")] @@ -978,6 +979,18 @@ public partial class SessionSkillsLoadedEvent : SessionEvent public required SessionSkillsLoadedData Data { get; set; } } +/// Represents the session.custom_agents_updated event. +public partial class SessionCustomAgentsUpdatedEvent : SessionEvent +{ + /// + [JsonIgnore] + public override string Type => "session.custom_agents_updated"; + + /// The session.custom_agents_updated event payload. + [JsonPropertyName("data")] + public required SessionCustomAgentsUpdatedData Data { get; set; } +} + /// Represents the session.mcp_servers_loaded event. public partial class SessionMcpServersLoadedEvent : SessionEvent { @@ -1954,6 +1967,11 @@ public partial class SkillInvokedData [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("pluginVersion")] public string? PluginVersion { get; set; } + + /// Description of the skill from its SKILL.md frontmatter. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("description")] + public string? Description { get; set; } } /// Sub-agent startup details including parent tool call and agent information. @@ -1990,6 +2008,26 @@ public partial class SubagentCompletedData /// Human-readable display name of the sub-agent. [JsonPropertyName("agentDisplayName")] public required string AgentDisplayName { get; set; } + + /// Model used by the sub-agent. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("model")] + public string? Model { get; set; } + + /// Total number of tool calls made by the sub-agent. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalToolCalls")] + public double? TotalToolCalls { get; set; } + + /// Total tokens (input + output) consumed by the sub-agent. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalTokens")] + public double? TotalTokens { get; set; } + + /// Wall-clock duration of the sub-agent execution in milliseconds. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("durationMs")] + public double? DurationMs { get; set; } } /// Sub-agent failure details including error message and agent information. @@ -2010,6 +2048,26 @@ public partial class SubagentFailedData /// Error message describing why the sub-agent failed. [JsonPropertyName("error")] public required string Error { get; set; } + + /// Model used by the sub-agent (if any model calls succeeded before failure). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("model")] + public string? Model { get; set; } + + /// Total number of tool calls made before the sub-agent failed. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalToolCalls")] + public double? TotalToolCalls { get; set; } + + /// Total tokens (input + output) consumed before the sub-agent failed. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("totalTokens")] + public double? TotalTokens { get; set; } + + /// Wall-clock duration of the sub-agent execution in milliseconds. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("durationMs")] + public double? DurationMs { get; set; } } /// Custom agent selection details including name and available tools. @@ -2387,6 +2445,22 @@ public partial class SessionSkillsLoadedData public required SessionSkillsLoadedDataSkillsItem[] Skills { get; set; } } +/// Event payload for . +public partial class SessionCustomAgentsUpdatedData +{ + /// Array of loaded custom agent metadata. + [JsonPropertyName("agents")] + public required SessionCustomAgentsUpdatedDataAgentsItem[] Agents { get; set; } + + /// Non-fatal warnings from agent loading. + [JsonPropertyName("warnings")] + public required string[] Warnings { get; set; } + + /// Fatal errors from agent loading. + [JsonPropertyName("errors")] + public required string[] Errors { get; set; } +} + /// Event payload for . public partial class SessionMcpServersLoadedData { @@ -3541,6 +3615,43 @@ public partial class SessionSkillsLoadedDataSkillsItem public string? Path { get; set; } } +/// Nested data type for SessionCustomAgentsUpdatedDataAgentsItem. +public partial class SessionCustomAgentsUpdatedDataAgentsItem +{ + /// Unique identifier for the agent. + [JsonPropertyName("id")] + public required string Id { get; set; } + + /// Internal name of the agent. + [JsonPropertyName("name")] + public required string Name { get; set; } + + /// Human-readable display name. + [JsonPropertyName("displayName")] + public required string DisplayName { get; set; } + + /// Description of what the agent does. + [JsonPropertyName("description")] + public required string Description { get; set; } + + /// Source location: user, project, inherited, remote, or plugin. + [JsonPropertyName("source")] + public required string Source { get; set; } + + /// List of tool names available to this agent. + [JsonPropertyName("tools")] + public required string[] Tools { get; set; } + + /// Whether the agent can be selected by the user. + [JsonPropertyName("userInvocable")] + public required bool UserInvocable { get; set; } + + /// Model override for this agent, if set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("model")] + public string? Model { get; set; } +} + /// Nested data type for SessionMcpServersLoadedDataServersItem. public partial class SessionMcpServersLoadedDataServersItem { @@ -3898,6 +4009,9 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SessionCompactionStartEvent))] [JsonSerializable(typeof(SessionContextChangedData))] [JsonSerializable(typeof(SessionContextChangedEvent))] +[JsonSerializable(typeof(SessionCustomAgentsUpdatedData))] +[JsonSerializable(typeof(SessionCustomAgentsUpdatedDataAgentsItem))] +[JsonSerializable(typeof(SessionCustomAgentsUpdatedEvent))] [JsonSerializable(typeof(SessionErrorData))] [JsonSerializable(typeof(SessionErrorEvent))] [JsonSerializable(typeof(SessionEvent))] diff --git a/go/generated_session_events.go b/go/generated_session_events.go index 591ff53af..b9cdbab47 100644 --- a/go/generated_session_events.go +++ b/go/generated_session_events.go @@ -657,6 +657,10 @@ type Data struct { // Model identifier used for this API call // // Model identifier that generated this tool call + // + // Model used by the sub-agent + // + // Model used by the sub-agent (if any model calls succeeded before failure) Model *string `json:"model,omitempty"` // Per-quota resource usage snapshots, keyed by quota identifier QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots,omitempty"` @@ -710,6 +714,8 @@ type Data struct { ToolTelemetry map[string]interface{} `json:"toolTelemetry,omitempty"` // Tool names that should be auto-approved when this skill is active AllowedTools []string `json:"allowedTools,omitempty"` + // Description of the skill from its SKILL.md frontmatter + Description *string `json:"description,omitempty"` // Name of the invoked skill // // Optional name identifier for the message source @@ -728,6 +734,16 @@ type Data struct { // // Internal name of the selected custom agent AgentName *string `json:"agentName,omitempty"` + // Wall-clock duration of the sub-agent execution in milliseconds + DurationMS *float64 `json:"durationMs,omitempty"` + // Total tokens (input + output) consumed by the sub-agent + // + // Total tokens (input + output) consumed before the sub-agent failed + TotalTokens *float64 `json:"totalTokens,omitempty"` + // Total number of tool calls made by the sub-agent + // + // Total number of tool calls made before the sub-agent failed + TotalToolCalls *float64 `json:"totalToolCalls,omitempty"` // List of tool names available to this agent, or null for all tools Tools []string `json:"tools"` // Unique identifier for this hook invocation @@ -793,6 +809,12 @@ type Data struct { RecommendedAction *string `json:"recommendedAction,omitempty"` // Array of resolved skill metadata Skills []Skill `json:"skills,omitempty"` + // Array of loaded custom agent metadata + Agents []DataAgent `json:"agents,omitempty"` + // Fatal errors from agent loading + Errors []string `json:"errors,omitempty"` + // Non-fatal warnings from agent loading + Warnings []string `json:"warnings,omitempty"` // Array of MCP server status summaries Servers []Server `json:"servers,omitempty"` // New connection status: connected, failed, pending, disabled, or not_configured @@ -801,6 +823,25 @@ type Data struct { Extensions []Extension `json:"extensions,omitempty"` } +type DataAgent struct { + // Description of what the agent does + Description string `json:"description"` + // Human-readable display name + DisplayName string `json:"displayName"` + // Unique identifier for the agent + ID string `json:"id"` + // Model override for this agent, if set + Model *string `json:"model,omitempty"` + // Internal name of the agent + Name string `json:"name"` + // Source location: user, project, inherited, remote, or plugin + Source string `json:"source"` + // List of tool names available to this agent + Tools []string `json:"tools"` + // Whether the agent can be selected by the user + UserInvocable bool `json:"userInvocable"` +} + // A user message attachment — a file, directory, code selection, blob, or GitHub reference // // # File attachment @@ -882,13 +923,13 @@ type Start struct { // Background tasks still running when the agent became idle type BackgroundTasks struct { // Currently running background agents - Agents []Agent `json:"agents"` + Agents []BackgroundTasksAgent `json:"agents"` // Currently running background shell commands Shells []Shell `json:"shells"` } // A background agent task -type Agent struct { +type BackgroundTasksAgent struct { // Unique identifier of the background agent AgentID string `json:"agentId"` // Type of the background agent @@ -1553,6 +1594,7 @@ const ( SessionEventTypeSessionCompactionComplete SessionEventType = "session.compaction_complete" SessionEventTypeSessionCompactionStart SessionEventType = "session.compaction_start" SessionEventTypeSessionContextChanged SessionEventType = "session.context_changed" + SessionEventTypeSessionCustomAgentsUpdated SessionEventType = "session.custom_agents_updated" SessionEventTypeSessionError SessionEventType = "session.error" SessionEventTypeSessionExtensionsLoaded SessionEventType = "session.extensions_loaded" SessionEventTypeSessionHandoff SessionEventType = "session.handoff" diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index d0d1398b2..42d9b6fb6 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.11-1", + "@github/copilot": "^1.0.11", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, @@ -662,26 +662,26 @@ } }, "node_modules/@github/copilot": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11-1.tgz", - "integrity": "sha512-W34C5TLJxE3SvB/TTt//LBNUbxNZV0tuobWUjBG7TnKQ4HHuJSzvQDE9dtxSfXlVyIzhoPgVYo0cOnN1cITfAA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11.tgz", + "integrity": "sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==", "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.11-1", - "@github/copilot-darwin-x64": "1.0.11-1", - "@github/copilot-linux-arm64": "1.0.11-1", - "@github/copilot-linux-x64": "1.0.11-1", - "@github/copilot-win32-arm64": "1.0.11-1", - "@github/copilot-win32-x64": "1.0.11-1" + "@github/copilot-darwin-arm64": "1.0.11", + "@github/copilot-darwin-x64": "1.0.11", + "@github/copilot-linux-arm64": "1.0.11", + "@github/copilot-linux-x64": "1.0.11", + "@github/copilot-win32-arm64": "1.0.11", + "@github/copilot-win32-x64": "1.0.11" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11-1.tgz", - "integrity": "sha512-VVL6qgV0MqWfi0Lh5xNuydgqq+QEWty8kXVq9gTHhu9RtVIxMjqF9Ay5IkiKTZf6lijTdMOdlRW6ds90dHQKtQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11.tgz", + "integrity": "sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==", "cpu": [ "arm64" ], @@ -695,9 +695,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11-1.tgz", - "integrity": "sha512-nHatPin4ZRUmNnSyZ0Vir32M/yWF5fg0IYCT3HOxJCvDxAe60P86FBMWIW5oH4BFWqLB37Vs/XUc5WK08miaLw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11.tgz", + "integrity": "sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==", "cpu": [ "x64" ], @@ -711,9 +711,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11-1.tgz", - "integrity": "sha512-Ybdb+gzJMKi8+poa+3XQGKPubgh6/LPJFkzhOumKdi/Jf1yOB3QmDXVltjuKbgaav4RZS+Gq8OvfdH4DL987SQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11.tgz", + "integrity": "sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==", "cpu": [ "arm64" ], @@ -727,9 +727,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11-1.tgz", - "integrity": "sha512-dXwxh9FkheEeeKV8mSW1JGmjjAb7ntE7zoc6GXJJaS1L91QcrfkZag6gbG3fdc2X9hwNZMUCRbVX2meqQidrIg==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11.tgz", + "integrity": "sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==", "cpu": [ "x64" ], @@ -743,9 +743,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11-1.tgz", - "integrity": "sha512-YEcACVYSfn2mc+xR+OBSX8XM5HvXMuFIF3NixfswEFzqJBMhHAj9ECtsdAkgG2QEFL8vLkOdpcVwbXqvdu4jxA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11.tgz", + "integrity": "sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==", "cpu": [ "arm64" ], @@ -759,9 +759,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11-1.tgz", - "integrity": "sha512-5YsCGeIDC62z7oQbWRjioBOX71JODYeYNif1PrJu2mUavCMuxHdt5/ZasLfX92HZpv+3zIrWTVnNUAaBVPKYlQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11.tgz", + "integrity": "sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==", "cpu": [ "x64" ], diff --git a/nodejs/package.json b/nodejs/package.json index 20525385d..4ccda703d 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -56,7 +56,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@github/copilot": "^1.0.11-1", + "@github/copilot": "^1.0.11", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json index a05be5360..cd2ce2305 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.10", + "@github/copilot": "^1.0.11", "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 3453f0191..91dc023e9 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -2124,6 +2124,10 @@ export type SessionEvent = * Version of the plugin this skill originated from, when applicable */ pluginVersion?: string; + /** + * Description of the skill from its SKILL.md frontmatter + */ + description?: string; }; } | { @@ -2200,6 +2204,22 @@ export type SessionEvent = * Human-readable display name of the sub-agent */ agentDisplayName: string; + /** + * Model used by the sub-agent + */ + model?: string; + /** + * Total number of tool calls made by the sub-agent + */ + totalToolCalls?: number; + /** + * Total tokens (input + output) consumed by the sub-agent + */ + totalTokens?: number; + /** + * Wall-clock duration of the sub-agent execution in milliseconds + */ + durationMs?: number; }; } | { @@ -2240,6 +2260,22 @@ export type SessionEvent = * Error message describing why the sub-agent failed */ error: string; + /** + * Model used by the sub-agent (if any model calls succeeded before failure) + */ + model?: string; + /** + * Total number of tool calls made before the sub-agent failed + */ + totalToolCalls?: number; + /** + * Total tokens (input + output) consumed before the sub-agent failed + */ + totalTokens?: number; + /** + * Wall-clock duration of the sub-agent execution in milliseconds + */ + durationMs?: number; }; } | { @@ -3400,6 +3436,69 @@ export type SessionEvent = }[]; }; } + | { + /** + * Unique event identifier (UUID v4), generated when the event is emitted + */ + id: string; + /** + * ISO 8601 timestamp when the event was created + */ + timestamp: string; + /** + * ID of the chronologically preceding event in the session, forming a linked chain. Null for the first event. + */ + parentId: string | null; + ephemeral: true; + type: "session.custom_agents_updated"; + data: { + /** + * Array of loaded custom agent metadata + */ + agents: { + /** + * Unique identifier for the agent + */ + id: string; + /** + * Internal name of the agent + */ + name: string; + /** + * Human-readable display name + */ + displayName: string; + /** + * Description of what the agent does + */ + description: string; + /** + * Source location: user, project, inherited, remote, or plugin + */ + source: string; + /** + * List of tool names available to this agent + */ + tools: string[]; + /** + * Whether the agent can be selected by the user + */ + userInvocable: boolean; + /** + * Model override for this agent, if set + */ + model?: string; + }[]; + /** + * Non-fatal warnings from agent loading + */ + warnings: string[]; + /** + * Fatal errors from agent loading + */ + errors: string[]; + }; + } | { /** * Unique event identifier (UUID v4), generated when the event is emitted diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index 9701a4d9f..9143c9b0b 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -5,8 +5,7 @@ from enum import Enum from dataclasses import dataclass -from typing import Any, TypeVar, cast -from collections.abc import Callable +from typing import Any, TypeVar, Callable, cast from datetime import datetime from uuid import UUID import dateutil.parser @@ -16,23 +15,18 @@ EnumT = TypeVar("EnumT", bound=Enum) -def from_float(x: Any) -> float: - assert isinstance(x, (float, int)) and not isinstance(x, bool) - return float(x) - - -def to_float(x: Any) -> float: - assert isinstance(x, (int, float)) +def from_str(x: Any) -> str: + assert isinstance(x, str) return x -def to_class(c: type[T], x: Any) -> dict: - assert isinstance(x, c) - return cast(Any, x).to_dict() +def from_list(f: Callable[[Any], T], x: Any) -> list[T]: + assert isinstance(x, list) + return [f(y) for y in x] -def from_str(x: Any) -> str: - assert isinstance(x, str) +def from_bool(x: Any) -> bool: + assert isinstance(x, bool) return x @@ -50,14 +44,24 @@ def from_union(fs, x): assert False -def to_enum(c: type[EnumT], x: Any) -> EnumT: +def from_float(x: Any) -> float: + assert isinstance(x, (float, int)) and not isinstance(x, bool) + return float(x) + + +def to_float(x: Any) -> float: + assert isinstance(x, (int, float)) + return x + + +def to_class(c: type[T], x: Any) -> dict: assert isinstance(x, c) - return x.value + return cast(Any, x).to_dict() -def from_list(f: Callable[[Any], T], x: Any) -> list[T]: - assert isinstance(x, list) - return [f(y) for y in x] +def to_enum(c: type[EnumT], x: Any) -> EnumT: + assert isinstance(x, c) + return x.value def from_dict(f: Callable[[Any], T], x: Any) -> dict[str, T]: @@ -65,11 +69,6 @@ def from_dict(f: Callable[[Any], T], x: Any) -> dict[str, T]: return { k: f(v) for (k, v) in x.items() } -def from_bool(x: Any) -> bool: - assert isinstance(x, bool) - return x - - def from_datetime(x: Any) -> datetime: return dateutil.parser.parse(x) @@ -88,6 +87,59 @@ class AgentMode(Enum): SHELL = "shell" +@dataclass +class DataAgent: + description: str + """Description of what the agent does""" + + display_name: str + """Human-readable display name""" + + id: str + """Unique identifier for the agent""" + + name: str + """Internal name of the agent""" + + source: str + """Source location: user, project, inherited, remote, or plugin""" + + tools: list[str] + """List of tool names available to this agent""" + + user_invocable: bool + """Whether the agent can be selected by the user""" + + model: str | None = None + """Model override for this agent, if set""" + + @staticmethod + def from_dict(obj: Any) -> 'DataAgent': + assert isinstance(obj, dict) + description = from_str(obj.get("description")) + display_name = from_str(obj.get("displayName")) + id = from_str(obj.get("id")) + name = from_str(obj.get("name")) + source = from_str(obj.get("source")) + tools = from_list(from_str, obj.get("tools")) + user_invocable = from_bool(obj.get("userInvocable")) + model = from_union([from_str, from_none], obj.get("model")) + return DataAgent(description, display_name, id, name, source, tools, user_invocable, model) + + def to_dict(self) -> dict: + result: dict = {} + result["description"] = from_str(self.description) + result["displayName"] = from_str(self.display_name) + result["id"] = from_str(self.id) + result["name"] = from_str(self.name) + result["source"] = from_str(self.source) + result["tools"] = from_list(from_str, self.tools) + result["userInvocable"] = from_bool(self.user_invocable) + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + return result + + @dataclass class LineRange: """Optional line range to scope the attachment to a specific section of the file""" @@ -312,7 +364,7 @@ def to_dict(self) -> dict: @dataclass -class Agent: +class BackgroundTasksAgent: """A background agent task""" agent_id: str @@ -325,12 +377,12 @@ class Agent: """Human-readable description of the agent task""" @staticmethod - def from_dict(obj: Any) -> 'Agent': + def from_dict(obj: Any) -> 'BackgroundTasksAgent': assert isinstance(obj, dict) agent_id = from_str(obj.get("agentId")) agent_type = from_str(obj.get("agentType")) description = from_union([from_str, from_none], obj.get("description")) - return Agent(agent_id, agent_type, description) + return BackgroundTasksAgent(agent_id, agent_type, description) def to_dict(self) -> dict: result: dict = {} @@ -370,7 +422,7 @@ def to_dict(self) -> dict: class BackgroundTasks: """Background tasks still running when the agent became idle""" - agents: list[Agent] + agents: list[BackgroundTasksAgent] """Currently running background agents""" shells: list[Shell] @@ -379,13 +431,13 @@ class BackgroundTasks: @staticmethod def from_dict(obj: Any) -> 'BackgroundTasks': assert isinstance(obj, dict) - agents = from_list(Agent.from_dict, obj.get("agents")) + agents = from_list(BackgroundTasksAgent.from_dict, obj.get("agents")) shells = from_list(Shell.from_dict, obj.get("shells")) return BackgroundTasks(agents, shells) def to_dict(self) -> dict: result: dict = {} - result["agents"] = from_list(lambda x: to_class(Agent, x), self.agents) + result["agents"] = from_list(lambda x: to_class(BackgroundTasksAgent, x), self.agents) result["shells"] = from_list(lambda x: to_class(Shell, x), self.shells) return result @@ -2283,6 +2335,10 @@ class Data: """Model identifier used for this API call Model identifier that generated this tool call + + Model used by the sub-agent + + Model used by the sub-agent (if any model calls succeeded before failure) """ quota_snapshots: dict[str, QuotaSnapshot] | None = None """Per-quota resource usage snapshots, keyed by quota identifier""" @@ -2349,6 +2405,9 @@ class Data: allowed_tools: list[str] | None = None """Tool names that should be auto-approved when this skill is active""" + description: str | None = None + """Description of the skill from its SKILL.md frontmatter""" + name: str | None = None """Name of the invoked skill @@ -2373,6 +2432,19 @@ class Data: Internal name of the selected custom agent """ + duration_ms: float | None = None + """Wall-clock duration of the sub-agent execution in milliseconds""" + + total_tokens: float | None = None + """Total tokens (input + output) consumed by the sub-agent + + Total tokens (input + output) consumed before the sub-agent failed + """ + total_tool_calls: float | None = None + """Total number of tool calls made by the sub-agent + + Total number of tool calls made before the sub-agent failed + """ tools: list[str] | None = None """List of tool names available to this agent, or null for all tools""" @@ -2466,6 +2538,15 @@ class Data: skills: list[Skill] | None = None """Array of resolved skill metadata""" + agents: list[DataAgent] | None = None + """Array of loaded custom agent metadata""" + + errors: list[str] | None = None + """Fatal errors from agent loading""" + + warnings: list[str] | None = None + """Non-fatal warnings from agent loading""" + servers: list[Server] | None = None """Array of MCP server status summaries""" @@ -2595,12 +2676,16 @@ def from_dict(obj: Any) -> 'Data': result = from_union([Result.from_dict, from_none], obj.get("result")) tool_telemetry = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("toolTelemetry")) allowed_tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("allowedTools")) + description = from_union([from_str, from_none], obj.get("description")) name = from_union([from_str, from_none], obj.get("name")) plugin_name = from_union([from_str, from_none], obj.get("pluginName")) plugin_version = from_union([from_str, from_none], obj.get("pluginVersion")) agent_description = from_union([from_str, from_none], obj.get("agentDescription")) agent_display_name = from_union([from_str, from_none], obj.get("agentDisplayName")) agent_name = from_union([from_str, from_none], obj.get("agentName")) + duration_ms = from_union([from_float, from_none], obj.get("durationMs")) + total_tokens = from_union([from_float, from_none], obj.get("totalTokens")) + total_tool_calls = from_union([from_float, from_none], obj.get("totalToolCalls")) tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) hook_invocation_id = from_union([from_str, from_none], obj.get("hookInvocationId")) hook_type = from_union([from_str, from_none], obj.get("hookType")) @@ -2629,10 +2714,13 @@ def from_dict(obj: Any) -> 'Data': plan_content = from_union([from_str, from_none], obj.get("planContent")) recommended_action = from_union([from_str, from_none], obj.get("recommendedAction")) skills = from_union([lambda x: from_list(Skill.from_dict, x), from_none], obj.get("skills")) + agents = from_union([lambda x: from_list(DataAgent.from_dict, x), from_none], obj.get("agents")) + errors = from_union([lambda x: from_list(from_str, x), from_none], obj.get("errors")) + warnings = from_union([lambda x: from_list(from_str, x), from_none], obj.get("warnings")) 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, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, provider_call_id, stack, status_code, url, 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, model, quota_snapshots, 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, name, plugin_name, plugin_version, agent_description, agent_display_name, agent_name, tools, hook_invocation_id, hook_type, input, output, metadata, role, kind, permission_request, allow_freeform, choices, question, elicitation_source, mode, requested_schema, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, actions, plan_content, recommended_action, skills, servers, status, extensions) + return Data(already_in_use, context, copilot_version, producer, reasoning_effort, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, provider_call_id, stack, status_code, url, 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, model, quota_snapshots, 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, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, actions, plan_content, recommended_action, skills, agents, errors, warnings, servers, status, extensions) def to_dict(self) -> dict: result: dict = {} @@ -2870,6 +2958,8 @@ def to_dict(self) -> dict: result["toolTelemetry"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.tool_telemetry) if self.allowed_tools is not None: result["allowedTools"] = from_union([lambda x: from_list(from_str, x), from_none], self.allowed_tools) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) if self.name is not None: result["name"] = from_union([from_str, from_none], self.name) if self.plugin_name is not None: @@ -2882,6 +2972,12 @@ def to_dict(self) -> dict: result["agentDisplayName"] = from_union([from_str, from_none], self.agent_display_name) if self.agent_name is not None: result["agentName"] = from_union([from_str, from_none], self.agent_name) + if self.duration_ms is not None: + result["durationMs"] = from_union([to_float, from_none], self.duration_ms) + if self.total_tokens is not None: + result["totalTokens"] = from_union([to_float, from_none], self.total_tokens) + if self.total_tool_calls is not None: + result["totalToolCalls"] = from_union([to_float, from_none], self.total_tool_calls) if self.tools is not None: result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) if self.hook_invocation_id is not None: @@ -2938,6 +3034,12 @@ def to_dict(self) -> dict: result["recommendedAction"] = from_union([from_str, from_none], self.recommended_action) if self.skills is not None: result["skills"] = from_union([lambda x: from_list(lambda x: to_class(Skill, x), x), from_none], self.skills) + if self.agents is not None: + result["agents"] = from_union([lambda x: from_list(lambda x: to_class(DataAgent, x), x), from_none], self.agents) + if self.errors is not None: + result["errors"] = from_union([lambda x: from_list(from_str, x), from_none], self.errors) + if self.warnings is not None: + result["warnings"] = from_union([lambda x: from_list(from_str, x), from_none], self.warnings) if self.servers is not None: result["servers"] = from_union([lambda x: from_list(lambda x: to_class(Server, x), x), from_none], self.servers) if self.status is not None: @@ -2979,6 +3081,7 @@ class SessionEventType(Enum): SESSION_COMPACTION_COMPLETE = "session.compaction_complete" SESSION_COMPACTION_START = "session.compaction_start" SESSION_CONTEXT_CHANGED = "session.context_changed" + SESSION_CUSTOM_AGENTS_UPDATED = "session.custom_agents_updated" SESSION_ERROR = "session.error" SESSION_EXTENSIONS_LOADED = "session.extensions_loaded" SESSION_HANDOFF = "session.handoff" diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json index 66616150f..5ab4ae513 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.11-1", + "@github/copilot": "^1.0.11", "@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.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11-1.tgz", - "integrity": "sha512-W34C5TLJxE3SvB/TTt//LBNUbxNZV0tuobWUjBG7TnKQ4HHuJSzvQDE9dtxSfXlVyIzhoPgVYo0cOnN1cITfAA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.11.tgz", + "integrity": "sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==", "dev": true, "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.11-1", - "@github/copilot-darwin-x64": "1.0.11-1", - "@github/copilot-linux-arm64": "1.0.11-1", - "@github/copilot-linux-x64": "1.0.11-1", - "@github/copilot-win32-arm64": "1.0.11-1", - "@github/copilot-win32-x64": "1.0.11-1" + "@github/copilot-darwin-arm64": "1.0.11", + "@github/copilot-darwin-x64": "1.0.11", + "@github/copilot-linux-arm64": "1.0.11", + "@github/copilot-linux-x64": "1.0.11", + "@github/copilot-win32-arm64": "1.0.11", + "@github/copilot-win32-x64": "1.0.11" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11-1.tgz", - "integrity": "sha512-VVL6qgV0MqWfi0Lh5xNuydgqq+QEWty8kXVq9gTHhu9RtVIxMjqF9Ay5IkiKTZf6lijTdMOdlRW6ds90dHQKtQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.11.tgz", + "integrity": "sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==", "cpu": [ "arm64" ], @@ -497,9 +497,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11-1.tgz", - "integrity": "sha512-nHatPin4ZRUmNnSyZ0Vir32M/yWF5fg0IYCT3HOxJCvDxAe60P86FBMWIW5oH4BFWqLB37Vs/XUc5WK08miaLw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.11.tgz", + "integrity": "sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==", "cpu": [ "x64" ], @@ -514,9 +514,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11-1.tgz", - "integrity": "sha512-Ybdb+gzJMKi8+poa+3XQGKPubgh6/LPJFkzhOumKdi/Jf1yOB3QmDXVltjuKbgaav4RZS+Gq8OvfdH4DL987SQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.11.tgz", + "integrity": "sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==", "cpu": [ "arm64" ], @@ -531,9 +531,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11-1.tgz", - "integrity": "sha512-dXwxh9FkheEeeKV8mSW1JGmjjAb7ntE7zoc6GXJJaS1L91QcrfkZag6gbG3fdc2X9hwNZMUCRbVX2meqQidrIg==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.11.tgz", + "integrity": "sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==", "cpu": [ "x64" ], @@ -548,9 +548,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11-1.tgz", - "integrity": "sha512-YEcACVYSfn2mc+xR+OBSX8XM5HvXMuFIF3NixfswEFzqJBMhHAj9ECtsdAkgG2QEFL8vLkOdpcVwbXqvdu4jxA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.11.tgz", + "integrity": "sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==", "cpu": [ "arm64" ], @@ -565,9 +565,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.11-1", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11-1.tgz", - "integrity": "sha512-5YsCGeIDC62z7oQbWRjioBOX71JODYeYNif1PrJu2mUavCMuxHdt5/ZasLfX92HZpv+3zIrWTVnNUAaBVPKYlQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.11.tgz", + "integrity": "sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==", "cpu": [ "x64" ], diff --git a/test/harness/package.json b/test/harness/package.json index 99dcb464a..9fe936ea7 100644 --- a/test/harness/package.json +++ b/test/harness/package.json @@ -11,7 +11,7 @@ "test": "vitest run" }, "devDependencies": { - "@github/copilot": "^1.0.11-1", + "@github/copilot": "^1.0.11", "@modelcontextprotocol/sdk": "^1.26.0", "@types/node": "^25.3.3", "openai": "^6.17.0",