From 216407b54fcfc510d30697bb49228bafa4834924 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 11:38:41 +0100 Subject: [PATCH 01/18] Rebase on main and regenerate all SDK output Rebased branch onto latest origin/main, resolved codegen script conflicts (csharp.ts emittedRpcClassSchemas Map merge, Session.cs and Types.cs type name updates), and regenerated all 4 languages from latest runtime schemas. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/features/image-input.md | 16 +- dotnet/src/Generated/Rpc.cs | 1001 +++---- dotnet/src/Generated/SessionEvents.cs | 475 ++-- dotnet/src/Session.cs | 28 +- dotnet/src/Types.cs | 6 +- dotnet/test/CloneTests.cs | 6 +- dotnet/test/ElicitationTests.cs | 18 +- .../MultiClientCommandsElicitationTests.cs | 4 +- dotnet/test/MultiClientTests.cs | 4 +- dotnet/test/RpcTests.cs | 12 +- dotnet/test/SessionEventSerializationTests.cs | 10 +- dotnet/test/SessionFsTests.cs | 26 +- dotnet/test/SessionTests.cs | 6 +- go/client.go | 4 +- go/client_test.go | 4 +- go/generated_session_events.go | 434 ++- go/internal/e2e/agent_and_compact_rpc_test.go | 4 +- go/internal/e2e/rpc_test.go | 32 +- go/internal/e2e/session_fs_test.go | 30 +- go/internal/e2e/session_test.go | 4 +- go/rpc/generated_rpc.go | 1309 +++++---- go/rpc/result_union.go | 22 +- go/session.go | 104 +- go/session_test.go | 4 +- go/types.go | 2 +- nodejs/src/generated/rpc.ts | 846 +++--- nodejs/src/generated/session-events.ts | 82 +- nodejs/src/types.ts | 6 +- nodejs/test/e2e/rpc.test.ts | 8 +- python/copilot/client.py | 25 +- python/copilot/generated/rpc.py | 2522 +++++++---------- python/copilot/generated/session_events.py | 578 ++-- python/copilot/session.py | 110 +- python/e2e/test_agent_and_compact_rpc.py | 8 +- python/e2e/test_rpc.py | 36 +- python/test_commands_and_elicitation.py | 8 +- python/test_rpc_timeout.py | 18 +- scripts/codegen/csharp.ts | 126 +- scripts/codegen/go.ts | 161 +- scripts/codegen/python.ts | 128 +- scripts/codegen/typescript.ts | 125 +- scripts/codegen/utils.ts | 174 +- .../prompts/attachments/csharp/Program.cs | 2 +- ...ompact_session_history_after_messages.yaml | 37 +- ...with_compaction_while_using_sessionfs.yaml | 38 +- 45 files changed, 4293 insertions(+), 4310 deletions(-) diff --git a/docs/features/image-input.md b/docs/features/image-input.md index 91d3cc75a..409130bbd 100644 --- a/docs/features/image-input.md +++ b/docs/features/image-input.md @@ -178,9 +178,9 @@ public static class ImageInputExample await session.SendAsync(new MessageOptions { Prompt = "Describe what you see in this image", - Attachments = new List + Attachments = new List { - new UserMessageDataAttachmentsItemFile + new UserMessageAttachmentFile { Path = "/absolute/path/to/screenshot.png", DisplayName = "screenshot.png", @@ -206,9 +206,9 @@ await using var session = await client.CreateSessionAsync(new SessionConfig await session.SendAsync(new MessageOptions { Prompt = "Describe what you see in this image", - Attachments = new List + Attachments = new List { - new UserMessageDataAttachmentsItemFile + new UserMessageAttachmentFile { Path = "/absolute/path/to/screenshot.png", DisplayName = "screenshot.png", @@ -396,9 +396,9 @@ public static class BlobAttachmentExample await session.SendAsync(new MessageOptions { Prompt = "Describe what you see in this image", - Attachments = new List + Attachments = new List { - new UserMessageDataAttachmentsItemBlob + new UserMessageAttachmentBlob { Data = base64ImageData, MimeType = "image/png", @@ -415,9 +415,9 @@ public static class BlobAttachmentExample await session.SendAsync(new MessageOptions { Prompt = "Describe what you see in this image", - Attachments = new List + Attachments = new List { - new UserMessageDataAttachmentsItemBlob + new UserMessageAttachmentBlob { Data = base64ImageData, MimeType = "image/png", diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 0caa4bbd2..800d70d25 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -29,11 +29,11 @@ public class PingResult /// Server timestamp in milliseconds. [JsonPropertyName("timestamp")] - public double Timestamp { get; set; } + public long Timestamp { get; set; } /// Server protocol version number. [JsonPropertyName("protocolVersion")] - public double ProtocolVersion { get; set; } + public long ProtocolVersion { get; set; } } /// RPC data type for Ping operations. @@ -64,28 +64,33 @@ public class ModelCapabilitiesLimitsVision public IList SupportedMediaTypes { get => field ??= []; set; } /// Maximum number of images per prompt. + [Range(typeof(long), "1", "long.MaxValue")] [JsonPropertyName("max_prompt_images")] - public double MaxPromptImages { get; set; } + public long MaxPromptImages { get; set; } /// Maximum image size in bytes. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_prompt_image_size")] - public double MaxPromptImageSize { get; set; } + public long MaxPromptImageSize { get; set; } } /// Token limits for prompts, outputs, and context window. public class ModelCapabilitiesLimits { /// Maximum number of prompt/input tokens. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_prompt_tokens")] - public double? MaxPromptTokens { get; set; } + public long? MaxPromptTokens { get; set; } /// Maximum number of output/completion tokens. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_output_tokens")] - public double? MaxOutputTokens { get; set; } + public long? MaxOutputTokens { get; set; } /// Maximum total context window size in tokens. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_context_window_tokens")] - public double MaxContextWindowTokens { get; set; } + public long MaxContextWindowTokens { get; set; } /// Vision-specific limits. [JsonPropertyName("vision")] @@ -156,12 +161,12 @@ public class Model public string? DefaultReasoningEffort { get; set; } } -/// RPC data type for ModelsList operations. -public class ModelsListResult +/// RPC data type for ModelList operations. +public class ModelList { /// List of available models with full metadata. [JsonPropertyName("models")] - public IList Models { get => field ??= []; set; } + public List Models { get; set; } } /// RPC data type for Tool operations. @@ -188,12 +193,12 @@ public class Tool public string? Instructions { get; set; } } -/// RPC data type for ToolsList operations. -public class ToolsListResult +/// RPC data type for ToolList operations. +public class ToolList { /// List of available built-in tools with metadata. [JsonPropertyName("tools")] - public IList Tools { get => field ??= []; set; } + public List Tools { get; set; } } /// RPC data type for ToolsList operations. @@ -204,24 +209,26 @@ internal class ToolsListRequest public string? Model { get; set; } } -/// RPC data type for AccountGetQuotaResultQuotaSnapshotsValue operations. -public class AccountGetQuotaResultQuotaSnapshotsValue +/// RPC data type for AccountQuotaSnapshot operations. +public class AccountQuotaSnapshot { /// Number of requests included in the entitlement. [JsonPropertyName("entitlementRequests")] - public double EntitlementRequests { get; set; } + public long EntitlementRequests { get; set; } /// Number of requests used so far this period. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("usedRequests")] - public double UsedRequests { get; set; } + public long UsedRequests { get; set; } /// Percentage of entitlement remaining. [JsonPropertyName("remainingPercentage")] public double RemainingPercentage { get; set; } /// Number of overage requests made this period. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("overage")] - public double Overage { get; set; } + public long Overage { get; set; } /// Whether pay-per-request usage is allowed when quota is exhausted. [JsonPropertyName("overageAllowedWithExhaustedQuota")] @@ -229,27 +236,28 @@ public class AccountGetQuotaResultQuotaSnapshotsValue /// Date when the quota resets (ISO 8601). [JsonPropertyName("resetDate")] - public string? ResetDate { get; set; } + public DateTimeOffset? ResetDate { get; set; } } -/// RPC data type for AccountGetQuota operations. -public class AccountGetQuotaResult +/// RPC data type for AccountQuota operations. +public class AccountQuota { /// Quota snapshots keyed by type (e.g., chat, completions, premium_interactions). [JsonPropertyName("quotaSnapshots")] - public IDictionary QuotaSnapshots { get => field ??= new Dictionary(); set; } + public IDictionary QuotaSnapshots { get => field ??= new Dictionary(); set; } } /// RPC data type for DiscoveredMcpServer operations. public class DiscoveredMcpServer { /// Server name (config key). + [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; - /// Server type: local, stdio, http, or sse. + /// Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio). [JsonPropertyName("type")] - public string? Type { get; set; } + public DiscoveredMcpServerType? Type { get; set; } /// Configuration source. [JsonPropertyName("source")] @@ -265,7 +273,7 @@ public class McpDiscoverResult { /// MCP servers discovered from all sources. [JsonPropertyName("servers")] - public IList Servers { get => field ??= []; set; } + public List Servers { get; set; } } /// RPC data type for McpDiscover operations. @@ -297,7 +305,7 @@ internal class SessionFsSetProviderRequest /// Path conventions used by this filesystem. [JsonPropertyName("conventions")] - public SessionFsSetProviderRequestConventions Conventions { get; set; } + public SessionFsSetProviderConventions Conventions { get; set; } } /// RPC data type for SessionsFork operations. @@ -322,16 +330,16 @@ internal class SessionsForkRequest public string? ToEventId { get; set; } } -/// RPC data type for SessionLog operations. -public class SessionLogResult +/// RPC data type for Log operations. +public class LogResult { /// The unique identifier of the emitted session event. [JsonPropertyName("eventId")] public Guid EventId { get; set; } } -/// RPC data type for SessionLog operations. -internal class SessionLogRequest +/// RPC data type for Log operations. +internal class LogRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -343,7 +351,7 @@ internal class SessionLogRequest /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". [JsonPropertyName("level")] - public SessionLogRequestLevel? Level { get; set; } + public SessionLogLevel? Level { get; set; } /// When true, the message is transient and not persisted to the session event log on disk. [JsonPropertyName("ephemeral")] @@ -356,8 +364,8 @@ internal class SessionLogRequest public string? Url { get; set; } } -/// RPC data type for SessionModelGetCurrent operations. -public class SessionModelGetCurrentResult +/// RPC data type for ModelCurrent operations. +public class ModelCurrent { /// Currently active model identifier. [JsonPropertyName("modelId")] @@ -372,8 +380,8 @@ internal class SessionModelGetCurrentRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionModelSwitchTo operations. -public class SessionModelSwitchToResult +/// RPC data type for ModelSwitchTo operations. +public class ModelSwitchToResult { /// Currently active model identifier after the switch. [JsonPropertyName("modelId")] @@ -400,28 +408,33 @@ public class ModelCapabilitiesOverrideLimitsVision public IList? SupportedMediaTypes { get; set; } /// Maximum number of images per prompt. + [Range(typeof(long), "1", "long.MaxValue")] [JsonPropertyName("max_prompt_images")] - public double? MaxPromptImages { get; set; } + public long? MaxPromptImages { get; set; } /// Maximum image size in bytes. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_prompt_image_size")] - public double? MaxPromptImageSize { get; set; } + public long? MaxPromptImageSize { get; set; } } /// Token limits for prompts, outputs, and context window. public class ModelCapabilitiesOverrideLimits { /// Gets or sets the max_prompt_tokens value. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_prompt_tokens")] - public double? MaxPromptTokens { get; set; } + public long? MaxPromptTokens { get; set; } /// Gets or sets the max_output_tokens value. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_output_tokens")] - public double? MaxOutputTokens { get; set; } + public long? MaxOutputTokens { get; set; } /// Maximum total context window size in tokens. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("max_context_window_tokens")] - public double? MaxContextWindowTokens { get; set; } + public long? MaxContextWindowTokens { get; set; } /// Gets or sets the vision value. [JsonPropertyName("vision")] @@ -440,8 +453,8 @@ public class ModelCapabilitiesOverride public ModelCapabilitiesOverrideLimits? Limits { get; set; } } -/// RPC data type for SessionModelSwitchTo operations. -internal class SessionModelSwitchToRequest +/// RPC data type for ModelSwitchTo operations. +internal class ModelSwitchToRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -460,14 +473,6 @@ internal class SessionModelSwitchToRequest public ModelCapabilitiesOverride? ModelCapabilities { get; set; } } -/// RPC data type for SessionModeGet operations. -public class SessionModeGetResult -{ - /// The current agent mode. - [JsonPropertyName("mode")] - public SessionModeGetResultMode Mode { get; set; } -} - /// RPC data type for SessionModeGet operations. internal class SessionModeGetRequest { @@ -476,28 +481,20 @@ internal class SessionModeGetRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionModeSet operations. -public class SessionModeSetResult -{ - /// The agent mode after switching. - [JsonPropertyName("mode")] - public SessionModeGetResultMode Mode { get; set; } -} - -/// RPC data type for SessionModeSet operations. -internal class SessionModeSetRequest +/// RPC data type for ModeSet operations. +internal class ModeSetRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; - /// The mode to switch to. Valid values: "interactive", "plan", "autopilot". + /// The agent mode. Valid values: "interactive", "plan", "autopilot". [JsonPropertyName("mode")] - public SessionModeGetResultMode Mode { get; set; } + public SessionMode Mode { get; set; } } -/// RPC data type for SessionPlanRead operations. -public class SessionPlanReadResult +/// RPC data type for Plan operations. +public class Plan { /// Whether the plan file exists in the workspace. [JsonPropertyName("exists")] @@ -520,13 +517,13 @@ internal class SessionPlanReadRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionPlanUpdate operations. -public class SessionPlanUpdateResult +/// RPC data type for PlanUpdate operations. +public class PlanUpdateResult { } -/// RPC data type for SessionPlanUpdate operations. -internal class SessionPlanUpdateRequest +/// RPC data type for PlanUpdate operations. +internal class PlanUpdateRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -537,8 +534,8 @@ internal class SessionPlanUpdateRequest public string Content { get; set; } = string.Empty; } -/// RPC data type for SessionPlanDelete operations. -public class SessionPlanDeleteResult +/// RPC data type for PlanDelete operations. +public class PlanDelete { } @@ -550,8 +547,8 @@ internal class SessionPlanDeleteRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionWorkspaceListFiles operations. -public class SessionWorkspaceListFilesResult +/// RPC data type for WorkspaceFiles operations. +public class WorkspaceFiles { /// Relative file paths in the workspace files directory. [JsonPropertyName("files")] @@ -566,16 +563,16 @@ internal class SessionWorkspaceListFilesRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionWorkspaceReadFile operations. -public class SessionWorkspaceReadFileResult +/// RPC data type for WorkspaceReadFile operations. +public class WorkspaceReadFileResult { /// File content as a UTF-8 string. [JsonPropertyName("content")] public string Content { get; set; } = string.Empty; } -/// RPC data type for SessionWorkspaceReadFile operations. -internal class SessionWorkspaceReadFileRequest +/// RPC data type for WorkspaceReadFile operations. +internal class WorkspaceReadFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -586,13 +583,13 @@ internal class SessionWorkspaceReadFileRequest public string Path { get; set; } = string.Empty; } -/// RPC data type for SessionWorkspaceCreateFile operations. -public class SessionWorkspaceCreateFileResult +/// RPC data type for WorkspaceCreateFile operations. +public class WorkspaceCreateFileResult { } -/// RPC data type for SessionWorkspaceCreateFile operations. -internal class SessionWorkspaceCreateFileRequest +/// RPC data type for WorkspaceCreateFile operations. +internal class WorkspaceCreateFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -607,18 +604,18 @@ internal class SessionWorkspaceCreateFileRequest public string Content { get; set; } = string.Empty; } -/// RPC data type for SessionFleetStart operations. +/// RPC data type for FleetStart operations. [Experimental(Diagnostics.Experimental)] -public class SessionFleetStartResult +public class FleetStartResult { /// Whether fleet mode was successfully activated. [JsonPropertyName("started")] public bool Started { get; set; } } -/// RPC data type for SessionFleetStart operations. +/// RPC data type for FleetStart operations. [Experimental(Diagnostics.Experimental)] -internal class SessionFleetStartRequest +internal class FleetStartRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -645,13 +642,13 @@ public class Agent public string Description { get; set; } = string.Empty; } -/// RPC data type for SessionAgentList operations. +/// RPC data type for AgentList operations. [Experimental(Diagnostics.Experimental)] -public class SessionAgentListResult +public class AgentList { /// Available custom agents. [JsonPropertyName("agents")] - public IList Agents { get => field ??= []; set; } + public List Agents { get; set; } } /// RPC data type for SessionAgentList operations. @@ -663,8 +660,8 @@ internal class SessionAgentListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionAgentGetCurrentResultAgent operations. -public class SessionAgentGetCurrentResultAgent +/// RPC data type for AgentCurrentAgent operations. +public class AgentCurrentAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -679,13 +676,13 @@ public class SessionAgentGetCurrentResultAgent public string Description { get; set; } = string.Empty; } -/// RPC data type for SessionAgentGetCurrent operations. +/// RPC data type for AgentCurrent operations. [Experimental(Diagnostics.Experimental)] -public class SessionAgentGetCurrentResult +public class AgentCurrent { /// Currently selected custom agent, or null if using the default agent. [JsonPropertyName("agent")] - public SessionAgentGetCurrentResultAgent? Agent { get; set; } + public AgentCurrentAgent? Agent { get; set; } } /// RPC data type for SessionAgentGetCurrent operations. @@ -698,7 +695,7 @@ internal class SessionAgentGetCurrentRequest } /// The newly selected custom agent. -public class SessionAgentSelectResultAgent +public class AgentSelectAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -713,18 +710,18 @@ public class SessionAgentSelectResultAgent public string Description { get; set; } = string.Empty; } -/// RPC data type for SessionAgentSelect operations. +/// RPC data type for AgentSelect operations. [Experimental(Diagnostics.Experimental)] -public class SessionAgentSelectResult +public class AgentSelectResult { /// The newly selected custom agent. [JsonPropertyName("agent")] - public SessionAgentSelectResultAgent Agent { get => field ??= new(); set; } + public AgentSelectAgent Agent { get => field ??= new(); set; } } -/// RPC data type for SessionAgentSelect operations. +/// RPC data type for AgentSelect operations. [Experimental(Diagnostics.Experimental)] -internal class SessionAgentSelectRequest +internal class AgentSelectRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -735,9 +732,9 @@ internal class SessionAgentSelectRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for SessionAgentDeselect operations. +/// RPC data type for AgentDeselect operations. [Experimental(Diagnostics.Experimental)] -public class SessionAgentDeselectResult +public class AgentDeselect { } @@ -750,13 +747,29 @@ internal class SessionAgentDeselectRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionAgentReload operations. +/// RPC data type for AgentReloadAgent operations. +public class AgentReloadAgent +{ + /// Unique identifier of the custom agent. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// Human-readable display name. + [JsonPropertyName("displayName")] + public string DisplayName { get; set; } = string.Empty; + + /// Description of the agent's purpose. + [JsonPropertyName("description")] + public string Description { get; set; } = string.Empty; +} + +/// RPC data type for AgentReload operations. [Experimental(Diagnostics.Experimental)] -public class SessionAgentReloadResult +public class AgentReload { /// Reloaded custom agents. [JsonPropertyName("agents")] - public IList Agents { get => field ??= []; set; } + public List Agents { get; set; } } /// RPC data type for SessionAgentReload operations. @@ -796,13 +809,13 @@ public class Skill public string? Path { get; set; } } -/// RPC data type for SessionSkillsList operations. +/// RPC data type for SkillList operations. [Experimental(Diagnostics.Experimental)] -public class SessionSkillsListResult +public class SkillList { /// Available skills. [JsonPropertyName("skills")] - public IList Skills { get => field ??= []; set; } + public List Skills { get; set; } } /// RPC data type for SessionSkillsList operations. @@ -814,15 +827,15 @@ internal class SessionSkillsListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionSkillsEnable operations. +/// RPC data type for SkillsEnable operations. [Experimental(Diagnostics.Experimental)] -public class SessionSkillsEnableResult +public class SkillsEnableResult { } -/// RPC data type for SessionSkillsEnable operations. +/// RPC data type for SkillsEnable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionSkillsEnableRequest +internal class SkillsEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -833,15 +846,15 @@ internal class SessionSkillsEnableRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for SessionSkillsDisable operations. +/// RPC data type for SkillsDisable operations. [Experimental(Diagnostics.Experimental)] -public class SessionSkillsDisableResult +public class SkillsDisableResult { } -/// RPC data type for SessionSkillsDisable operations. +/// RPC data type for SkillsDisable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionSkillsDisableRequest +internal class SkillsDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -852,9 +865,9 @@ internal class SessionSkillsDisableRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for SessionSkillsReload operations. +/// RPC data type for SkillsReload operations. [Experimental(Diagnostics.Experimental)] -public class SessionSkillsReloadResult +public class SkillsReload { } @@ -867,33 +880,34 @@ internal class SessionSkillsReloadRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for Server operations. -public class Server +/// RPC data type for McpServer operations. +public class McpServer { /// Server name (config key). + [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. [JsonPropertyName("status")] - public ServerStatus Status { get; set; } + public McpServerStatus Status { get; set; } /// Configuration source: user, workspace, plugin, or builtin. [JsonPropertyName("source")] - public string? Source { get; set; } + public DiscoveredMcpServerSource? Source { get; set; } /// Error message if the server failed to connect. [JsonPropertyName("error")] public string? Error { get; set; } } -/// RPC data type for SessionMcpList operations. +/// RPC data type for McpList operations. [Experimental(Diagnostics.Experimental)] -public class SessionMcpListResult +public class McpList { /// Configured MCP servers. [JsonPropertyName("servers")] - public IList Servers { get => field ??= []; set; } + public List Servers { get; set; } } /// RPC data type for SessionMcpList operations. @@ -905,47 +919,49 @@ internal class SessionMcpListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionMcpEnable operations. +/// RPC data type for McpEnable operations. [Experimental(Diagnostics.Experimental)] -public class SessionMcpEnableResult +public class McpEnableResult { } -/// RPC data type for SessionMcpEnable operations. +/// RPC data type for McpEnable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionMcpEnableRequest +internal class McpEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; /// Name of the MCP server to enable. + [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] [JsonPropertyName("serverName")] public string ServerName { get; set; } = string.Empty; } -/// RPC data type for SessionMcpDisable operations. +/// RPC data type for McpDisable operations. [Experimental(Diagnostics.Experimental)] -public class SessionMcpDisableResult +public class McpDisableResult { } -/// RPC data type for SessionMcpDisable operations. +/// RPC data type for McpDisable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionMcpDisableRequest +internal class McpDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; /// Name of the MCP server to disable. + [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] [JsonPropertyName("serverName")] public string ServerName { get; set; } = string.Empty; } -/// RPC data type for SessionMcpReload operations. +/// RPC data type for McpReload operations. [Experimental(Diagnostics.Experimental)] -public class SessionMcpReloadResult +public class McpReload { } @@ -978,13 +994,13 @@ public class Plugin public bool Enabled { get; set; } } -/// RPC data type for SessionPluginsList operations. +/// RPC data type for PluginList operations. [Experimental(Diagnostics.Experimental)] -public class SessionPluginsListResult +public class PluginList { /// Installed plugins. [JsonPropertyName("plugins")] - public IList Plugins { get => field ??= []; set; } + public List Plugins { get; set; } } /// RPC data type for SessionPluginsList operations. @@ -1020,13 +1036,13 @@ public class Extension public long? Pid { get; set; } } -/// RPC data type for SessionExtensionsList operations. +/// RPC data type for ExtensionList operations. [Experimental(Diagnostics.Experimental)] -public class SessionExtensionsListResult +public class ExtensionList { /// Discovered extensions and their current status. [JsonPropertyName("extensions")] - public IList Extensions { get => field ??= []; set; } + public List Extensions { get; set; } } /// RPC data type for SessionExtensionsList operations. @@ -1038,15 +1054,15 @@ internal class SessionExtensionsListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionExtensionsEnable operations. +/// RPC data type for ExtensionsEnable operations. [Experimental(Diagnostics.Experimental)] -public class SessionExtensionsEnableResult +public class ExtensionsEnableResult { } -/// RPC data type for SessionExtensionsEnable operations. +/// RPC data type for ExtensionsEnable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionExtensionsEnableRequest +internal class ExtensionsEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1057,15 +1073,15 @@ internal class SessionExtensionsEnableRequest public string Id { get; set; } = string.Empty; } -/// RPC data type for SessionExtensionsDisable operations. +/// RPC data type for ExtensionsDisable operations. [Experimental(Diagnostics.Experimental)] -public class SessionExtensionsDisableResult +public class ExtensionsDisableResult { } -/// RPC data type for SessionExtensionsDisable operations. +/// RPC data type for ExtensionsDisable operations. [Experimental(Diagnostics.Experimental)] -internal class SessionExtensionsDisableRequest +internal class ExtensionsDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1076,9 +1092,9 @@ internal class SessionExtensionsDisableRequest public string Id { get; set; } = string.Empty; } -/// RPC data type for SessionExtensionsReload operations. +/// RPC data type for ExtensionsReload operations. [Experimental(Diagnostics.Experimental)] -public class SessionExtensionsReloadResult +public class ExtensionsReload { } @@ -1091,16 +1107,16 @@ internal class SessionExtensionsReloadRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionToolsHandlePendingToolCall operations. -public class SessionToolsHandlePendingToolCallResult +/// RPC data type for HandleToolCall operations. +public class HandleToolCallResult { /// Whether the tool call result was handled successfully. [JsonPropertyName("success")] public bool Success { get; set; } } -/// RPC data type for SessionToolsHandlePendingToolCall operations. -internal class SessionToolsHandlePendingToolCallRequest +/// RPC data type for ToolsHandlePendingToolCall operations. +internal class ToolsHandlePendingToolCallRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1119,16 +1135,16 @@ internal class SessionToolsHandlePendingToolCallRequest public string? Error { get; set; } } -/// RPC data type for SessionCommandsHandlePendingCommand operations. -public class SessionCommandsHandlePendingCommandResult +/// RPC data type for CommandsHandlePendingCommand operations. +public class CommandsHandlePendingCommandResult { /// Whether the command was handled successfully. [JsonPropertyName("success")] public bool Success { get; set; } } -/// RPC data type for SessionCommandsHandlePendingCommand operations. -internal class SessionCommandsHandlePendingCommandRequest +/// RPC data type for CommandsHandlePendingCommand operations. +internal class CommandsHandlePendingCommandRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1143,12 +1159,12 @@ internal class SessionCommandsHandlePendingCommandRequest public string? Error { get; set; } } -/// RPC data type for SessionUiElicitation operations. -public class SessionUiElicitationResult +/// The elicitation response (accept with form values, decline, or cancel). +public class UiElicitationResponse { /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). [JsonPropertyName("action")] - public SessionUiElicitationResultAction Action { get; set; } + public ElicitationResponseAction Action { get; set; } /// The form values submitted by the user (present when action is 'accept'). [JsonPropertyName("content")] @@ -1156,7 +1172,7 @@ public class SessionUiElicitationResult } /// JSON Schema describing the form fields to present to the user. -public class SessionUiElicitationRequestRequestedSchema +public class UiElicitationSchema { /// Schema type indicator (always 'object'). [JsonPropertyName("type")] @@ -1171,8 +1187,8 @@ public class SessionUiElicitationRequestRequestedSchema public IList? Required { get; set; } } -/// RPC data type for SessionUiElicitation operations. -internal class SessionUiElicitationRequest +/// RPC data type for UiElicitation operations. +internal class UiElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1184,31 +1200,19 @@ internal class SessionUiElicitationRequest /// JSON Schema describing the form fields to present to the user. [JsonPropertyName("requestedSchema")] - public SessionUiElicitationRequestRequestedSchema RequestedSchema { get => field ??= new(); set; } + public UiElicitationSchema RequestedSchema { get => field ??= new(); set; } } -/// RPC data type for SessionUiHandlePendingElicitation operations. -public class SessionUiHandlePendingElicitationResult +/// RPC data type for UiElicitation operations. +public class UiElicitationResult { /// Whether the response was accepted. False if the request was already resolved by another client. [JsonPropertyName("success")] public bool Success { get; set; } } -/// The elicitation response (accept with form values, decline, or cancel). -public class SessionUiHandlePendingElicitationRequestResult -{ - /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). - [JsonPropertyName("action")] - public SessionUiElicitationResultAction Action { get; set; } - - /// The form values submitted by the user (present when action is 'accept'). - [JsonPropertyName("content")] - public IDictionary? Content { get; set; } -} - -/// RPC data type for SessionUiHandlePendingElicitation operations. -internal class SessionUiHandlePendingElicitationRequest +/// RPC data type for HandlePendingElicitation operations. +internal class HandlePendingElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1220,19 +1224,19 @@ internal class SessionUiHandlePendingElicitationRequest /// The elicitation response (accept with form values, decline, or cancel). [JsonPropertyName("result")] - public SessionUiHandlePendingElicitationRequestResult Result { get => field ??= new(); set; } + public UiElicitationResponse Result { get => field ??= new(); set; } } -/// RPC data type for SessionPermissionsHandlePendingPermissionRequest operations. -public class SessionPermissionsHandlePendingPermissionRequestResult +/// RPC data type for PermissionRequest operations. +public class PermissionRequestResult { /// Whether the permission request was handled successfully. [JsonPropertyName("success")] public bool Success { get; set; } } -/// RPC data type for SessionPermissionsHandlePendingPermissionRequest operations. -internal class SessionPermissionsHandlePendingPermissionRequestRequest +/// RPC data type for PermissionDecision operations. +internal class PermissionDecisionRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1247,16 +1251,16 @@ internal class SessionPermissionsHandlePendingPermissionRequestRequest public object Result { get; set; } = null!; } -/// RPC data type for SessionShellExec operations. -public class SessionShellExecResult +/// RPC data type for ShellExec operations. +public class ShellExecResult { /// Unique identifier for tracking streamed output. [JsonPropertyName("processId")] public string ProcessId { get; set; } = string.Empty; } -/// RPC data type for SessionShellExec operations. -internal class SessionShellExecRequest +/// RPC data type for ShellExec operations. +internal class ShellExecRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1271,20 +1275,22 @@ internal class SessionShellExecRequest public string? Cwd { get; set; } /// Timeout in milliseconds (default: 30000). + [Range(typeof(long), "0", "long.MaxValue")] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("timeout")] - public double? Timeout { get; set; } + public TimeSpan? Timeout { get; set; } } -/// RPC data type for SessionShellKill operations. -public class SessionShellKillResult +/// RPC data type for ShellKill operations. +public class ShellKillResult { /// Whether the signal was sent successfully. [JsonPropertyName("killed")] public bool Killed { get; set; } } -/// RPC data type for SessionShellKill operations. -internal class SessionShellKillRequest +/// RPC data type for ShellKill operations. +internal class ShellKillRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1296,56 +1302,64 @@ internal class SessionShellKillRequest /// Signal to send (default: SIGTERM). [JsonPropertyName("signal")] - public SessionShellKillRequestSignal? Signal { get; set; } + public ShellKillSignal? Signal { get; set; } } /// Post-compaction context window usage breakdown. -public class SessionHistoryCompactResultContextWindow +public class HistoryCompactContextWindow { /// Maximum token count for the model's context window. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("tokenLimit")] - public double TokenLimit { get; set; } + public long TokenLimit { get; set; } /// Current total tokens in the context window (system + conversation + tool definitions). + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("currentTokens")] - public double CurrentTokens { get; set; } + public long CurrentTokens { get; set; } /// Current number of messages in the conversation. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("messagesLength")] - public double MessagesLength { get; set; } + public long MessagesLength { get; set; } /// Token count from system message(s). + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("systemTokens")] - public double? SystemTokens { get; set; } + public long? SystemTokens { get; set; } /// Token count from non-system messages (user, assistant, tool). + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("conversationTokens")] - public double? ConversationTokens { get; set; } + public long? ConversationTokens { get; set; } /// Token count from tool definitions. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("toolDefinitionsTokens")] - public double? ToolDefinitionsTokens { get; set; } + public long? ToolDefinitionsTokens { get; set; } } -/// RPC data type for SessionHistoryCompact operations. +/// RPC data type for HistoryCompact operations. [Experimental(Diagnostics.Experimental)] -public class SessionHistoryCompactResult +public class HistoryCompact { /// Whether compaction completed successfully. [JsonPropertyName("success")] public bool Success { get; set; } /// Number of tokens freed by compaction. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("tokensRemoved")] - public double TokensRemoved { get; set; } + public long TokensRemoved { get; set; } /// Number of messages removed during compaction. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("messagesRemoved")] - public double MessagesRemoved { get; set; } + public long MessagesRemoved { get; set; } /// Post-compaction context window usage breakdown. [JsonPropertyName("contextWindow")] - public SessionHistoryCompactResultContextWindow? ContextWindow { get; set; } + public HistoryCompactContextWindow? ContextWindow { get; set; } } /// RPC data type for SessionHistoryCompact operations. @@ -1357,18 +1371,19 @@ internal class SessionHistoryCompactRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionHistoryTruncate operations. +/// RPC data type for HistoryTruncate operations. [Experimental(Diagnostics.Experimental)] -public class SessionHistoryTruncateResult +public class HistoryTruncateResult { /// Number of events that were removed. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("eventsRemoved")] - public double EventsRemoved { get; set; } + public long EventsRemoved { get; set; } } -/// RPC data type for SessionHistoryTruncate operations. +/// RPC data type for HistoryTruncate operations. [Experimental(Diagnostics.Experimental)] -internal class SessionHistoryTruncateRequest +internal class HistoryTruncateRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1380,7 +1395,7 @@ internal class SessionHistoryTruncateRequest } /// Aggregated code change metrics. -public class SessionUsageGetMetricsResultCodeChanges +public class UsageMetricsCodeChanges { /// Total lines of code added. [JsonPropertyName("linesAdded")] @@ -1396,7 +1411,7 @@ public class SessionUsageGetMetricsResultCodeChanges } /// Request count and cost metrics for this model. -public class SessionUsageGetMetricsResultModelMetricsValueRequests +public class UsageMetricsModelMetricRequests { /// Number of API requests made with this model. [JsonPropertyName("count")] @@ -1408,52 +1423,64 @@ public class SessionUsageGetMetricsResultModelMetricsValueRequests } /// Token usage metrics for this model. -public class SessionUsageGetMetricsResultModelMetricsValueUsage +public class UsageMetricsModelMetricUsage { /// Total input tokens consumed. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("inputTokens")] public long InputTokens { get; set; } /// Total output tokens produced. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("outputTokens")] public long OutputTokens { get; set; } /// Total tokens read from prompt cache. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("cacheReadTokens")] public long CacheReadTokens { get; set; } /// Total tokens written to prompt cache. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("cacheWriteTokens")] public long CacheWriteTokens { get; set; } + + /// Total output tokens used for reasoning. + [Range(typeof(long), "0", "long.MaxValue")] + [JsonPropertyName("reasoningTokens")] + public long? ReasoningTokens { get; set; } } -/// RPC data type for SessionUsageGetMetricsResultModelMetricsValue operations. -public class SessionUsageGetMetricsResultModelMetricsValue +/// RPC data type for UsageMetricsModelMetric operations. +public class UsageMetricsModelMetric { /// Request count and cost metrics for this model. [JsonPropertyName("requests")] - public SessionUsageGetMetricsResultModelMetricsValueRequests Requests { get => field ??= new(); set; } + public UsageMetricsModelMetricRequests Requests { get => field ??= new(); set; } /// Token usage metrics for this model. [JsonPropertyName("usage")] - public SessionUsageGetMetricsResultModelMetricsValueUsage Usage { get => field ??= new(); set; } + public UsageMetricsModelMetricUsage Usage { get => field ??= new(); set; } } -/// RPC data type for SessionUsageGetMetrics operations. +/// RPC data type for UsageMetrics operations. [Experimental(Diagnostics.Experimental)] -public class SessionUsageGetMetricsResult +public class UsageMetrics { /// Total user-initiated premium request cost across all models (may be fractional due to multipliers). [JsonPropertyName("totalPremiumRequestCost")] public double TotalPremiumRequestCost { get; set; } /// Raw count of user-initiated API requests. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("totalUserRequests")] public long TotalUserRequests { get; set; } /// Total time spent in model API calls (milliseconds). + [Range(0, double.MaxValue)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("totalApiDurationMs")] - public double TotalApiDurationMs { get; set; } + public TimeSpan TotalApiDurationMs { get; set; } /// Session start timestamp (epoch milliseconds). [JsonPropertyName("sessionStartTime")] @@ -1461,21 +1488,23 @@ public class SessionUsageGetMetricsResult /// Aggregated code change metrics. [JsonPropertyName("codeChanges")] - public SessionUsageGetMetricsResultCodeChanges CodeChanges { get => field ??= new(); set; } + public UsageMetricsCodeChanges CodeChanges { get => field ??= new(); set; } /// Per-model token and request metrics, keyed by model identifier. [JsonPropertyName("modelMetrics")] - public IDictionary ModelMetrics { get => field ??= new Dictionary(); set; } + public IDictionary ModelMetrics { get => field ??= new Dictionary(); set; } /// Currently active model identifier. [JsonPropertyName("currentModel")] public string? CurrentModel { get; set; } /// Input tokens from the most recent main-agent API call. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("lastCallInputTokens")] public long LastCallInputTokens { get; set; } /// Output tokens from the most recent main-agent API call. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("lastCallOutputTokens")] public long LastCallOutputTokens { get; set; } } @@ -1498,7 +1527,7 @@ public class SessionFsReadFileResult } /// RPC data type for SessionFsReadFile operations. -public class SessionFsReadFileParams +public class SessionFsReadFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1510,7 +1539,7 @@ public class SessionFsReadFileParams } /// RPC data type for SessionFsWriteFile operations. -public class SessionFsWriteFileParams +public class SessionFsWriteFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1525,12 +1554,13 @@ public class SessionFsWriteFileParams public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("mode")] - public double? Mode { get; set; } + public long? Mode { get; set; } } /// RPC data type for SessionFsAppendFile operations. -public class SessionFsAppendFileParams +public class SessionFsAppendFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1545,8 +1575,9 @@ public class SessionFsAppendFileParams public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("mode")] - public double? Mode { get; set; } + public long? Mode { get; set; } } /// RPC data type for SessionFsExists operations. @@ -1558,7 +1589,7 @@ public class SessionFsExistsResult } /// RPC data type for SessionFsExists operations. -public class SessionFsExistsParams +public class SessionFsExistsRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1581,20 +1612,21 @@ public class SessionFsStatResult public bool IsDirectory { get; set; } /// File size in bytes. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("size")] - public double Size { get; set; } + public long Size { get; set; } /// ISO 8601 timestamp of last modification. [JsonPropertyName("mtime")] - public string Mtime { get; set; } = string.Empty; + public DateTimeOffset Mtime { get; set; } /// ISO 8601 timestamp of creation. [JsonPropertyName("birthtime")] - public string Birthtime { get; set; } = string.Empty; + public DateTimeOffset Birthtime { get; set; } } /// RPC data type for SessionFsStat operations. -public class SessionFsStatParams +public class SessionFsStatRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1606,7 +1638,7 @@ public class SessionFsStatParams } /// RPC data type for SessionFsMkdir operations. -public class SessionFsMkdirParams +public class SessionFsMkdirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1621,8 +1653,9 @@ public class SessionFsMkdirParams public bool? Recursive { get; set; } /// Optional POSIX-style mode for newly created directories. + [Range(typeof(long), "0", "long.MaxValue")] [JsonPropertyName("mode")] - public double? Mode { get; set; } + public long? Mode { get; set; } } /// RPC data type for SessionFsReaddir operations. @@ -1634,7 +1667,7 @@ public class SessionFsReaddirResult } /// RPC data type for SessionFsReaddir operations. -public class SessionFsReaddirParams +public class SessionFsReaddirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1645,8 +1678,8 @@ public class SessionFsReaddirParams public string Path { get; set; } = string.Empty; } -/// RPC data type for Entry operations. -public class Entry +/// RPC data type for SessionFsReaddirWithTypesEntry operations. +public class SessionFsReaddirWithTypesEntry { /// Entry name. [JsonPropertyName("name")] @@ -1654,7 +1687,7 @@ public class Entry /// Entry type. [JsonPropertyName("type")] - public EntryType Type { get; set; } + public SessionFsReaddirWithTypesEntryType Type { get; set; } } /// RPC data type for SessionFsReaddirWithTypes operations. @@ -1662,11 +1695,11 @@ public class SessionFsReaddirWithTypesResult { /// Directory entries with type information. [JsonPropertyName("entries")] - public IList Entries { get => field ??= []; set; } + public List Entries { get; set; } } /// RPC data type for SessionFsReaddirWithTypes operations. -public class SessionFsReaddirWithTypesParams +public class SessionFsReaddirWithTypesRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1678,7 +1711,7 @@ public class SessionFsReaddirWithTypesParams } /// RPC data type for SessionFsRm operations. -public class SessionFsRmParams +public class SessionFsRmRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1698,7 +1731,7 @@ public class SessionFsRmParams } /// RPC data type for SessionFsRename operations. -public class SessionFsRenameParams +public class SessionFsRenameRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1713,6 +1746,25 @@ public class SessionFsRenameParams public string Dest { get; set; } = string.Empty; } +/// Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio). +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum DiscoveredMcpServerType +{ + /// The stdio variant. + [JsonStringEnumMemberName("stdio")] + Stdio, + /// The http variant. + [JsonStringEnumMemberName("http")] + Http, + /// The sse variant. + [JsonStringEnumMemberName("sse")] + Sse, + /// The memory variant. + [JsonStringEnumMemberName("memory")] + Memory, +} + + /// Configuration source. [JsonConverter(typeof(JsonStringEnumConverter))] public enum DiscoveredMcpServerSource @@ -1733,8 +1785,8 @@ public enum DiscoveredMcpServerSource /// Path conventions used by this filesystem. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionFsSetProviderRequestConventions +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionFsSetProviderConventions { /// The windows variant. [JsonStringEnumMemberName("windows")] @@ -1746,8 +1798,8 @@ public enum SessionFsSetProviderRequestConventions /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionLogRequestLevel +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionLogLevel { /// The info variant. [JsonStringEnumMemberName("info")] @@ -1761,9 +1813,9 @@ public enum SessionLogRequestLevel } -/// The current agent mode. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionModeGetResultMode +/// The agent mode. Valid values: "interactive", "plan", "autopilot". +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionMode { /// The interactive variant. [JsonStringEnumMemberName("interactive")] @@ -1778,8 +1830,8 @@ public enum SessionModeGetResultMode /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ServerStatus +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum McpServerStatus { /// The connected variant. [JsonStringEnumMemberName("connected")] @@ -1835,8 +1887,8 @@ public enum ExtensionStatus /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionUiElicitationResultAction +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ElicitationResponseAction { /// The accept variant. [JsonStringEnumMemberName("accept")] @@ -1851,8 +1903,8 @@ public enum SessionUiElicitationResultAction /// Signal to send (default: SIGTERM). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionShellKillRequestSignal +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ShellKillSignal { /// The SIGTERM variant. [JsonStringEnumMemberName("SIGTERM")] @@ -1867,8 +1919,8 @@ public enum SessionShellKillRequestSignal /// Entry type. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum EntryType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionFsReaddirWithTypesEntryType { /// The file variant. [JsonStringEnumMemberName("file")] @@ -1932,9 +1984,9 @@ internal ServerModelsApi(JsonRpc rpc) } /// Calls "models.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { - return await CopilotClient.InvokeRpcAsync(_rpc, "models.list", [], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "models.list", [], cancellationToken); } } @@ -1949,10 +2001,10 @@ internal ServerToolsApi(JsonRpc rpc) } /// Calls "tools.list". - public async Task ListAsync(string? model = null, CancellationToken cancellationToken = default) + public async Task ListAsync(string? model = null, CancellationToken cancellationToken = default) { var request = new ToolsListRequest { Model = model }; - return await CopilotClient.InvokeRpcAsync(_rpc, "tools.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "tools.list", [request], cancellationToken); } } @@ -1967,9 +2019,9 @@ internal ServerAccountApi(JsonRpc rpc) } /// Calls "account.getQuota". - public async Task GetQuotaAsync(CancellationToken cancellationToken = default) + public async Task GetQuotaAsync(CancellationToken cancellationToken = default) { - return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [], cancellationToken); } } @@ -2002,7 +2054,7 @@ internal ServerSessionFsApi(JsonRpc rpc) } /// Calls "sessionFs.setProvider". - public async Task SetProviderAsync(string initialCwd, string sessionStatePath, SessionFsSetProviderRequestConventions conventions, CancellationToken cancellationToken = default) + public async Task SetProviderAsync(string initialCwd, string sessionStatePath, SessionFsSetProviderConventions conventions, CancellationToken cancellationToken = default) { var request = new SessionFsSetProviderRequest { InitialCwd = initialCwd, SessionStatePath = sessionStatePath, Conventions = conventions }; return await CopilotClient.InvokeRpcAsync(_rpc, "sessionFs.setProvider", [request], cancellationToken); @@ -2109,10 +2161,10 @@ internal SessionRpc(JsonRpc rpc, string sessionId) public UsageApi Usage { get; } /// Calls "session.log". - public async Task LogAsync(string message, SessionLogRequestLevel? level = null, bool? ephemeral = null, string? url = null, CancellationToken cancellationToken = default) + public async Task LogAsync(string message, SessionLogLevel? level = null, bool? ephemeral = null, string? url = null, CancellationToken cancellationToken = default) { - var request = new SessionLogRequest { SessionId = _sessionId, Message = message, Level = level, Ephemeral = ephemeral, Url = url }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.log", [request], cancellationToken); + var request = new LogRequest { SessionId = _sessionId, Message = message, Level = level, Ephemeral = ephemeral, Url = url }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.log", [request], cancellationToken); } } @@ -2129,17 +2181,17 @@ internal ModelApi(JsonRpc rpc, string sessionId) } /// Calls "session.model.getCurrent". - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionModelGetCurrentRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.getCurrent", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.getCurrent", [request], cancellationToken); } /// Calls "session.model.switchTo". - public async Task SwitchToAsync(string modelId, string? reasoningEffort = null, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default) + public async Task SwitchToAsync(string modelId, string? reasoningEffort = null, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default) { - var request = new SessionModelSwitchToRequest { SessionId = _sessionId, ModelId = modelId, ReasoningEffort = reasoningEffort, ModelCapabilities = modelCapabilities }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.switchTo", [request], cancellationToken); + var request = new ModelSwitchToRequest { SessionId = _sessionId, ModelId = modelId, ReasoningEffort = reasoningEffort, ModelCapabilities = modelCapabilities }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.switchTo", [request], cancellationToken); } } @@ -2156,17 +2208,17 @@ internal ModeApi(JsonRpc rpc, string sessionId) } /// Calls "session.mode.get". - public async Task GetAsync(CancellationToken cancellationToken = default) + public async Task GetAsync(CancellationToken cancellationToken = default) { var request = new SessionModeGetRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.get", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.get", [request], cancellationToken); } /// Calls "session.mode.set". - public async Task SetAsync(SessionModeGetResultMode mode, CancellationToken cancellationToken = default) + public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken = default) { - var request = new SessionModeSetRequest { SessionId = _sessionId, Mode = mode }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.set", [request], cancellationToken); + var request = new ModeSetRequest { SessionId = _sessionId, Mode = mode }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.set", [request], cancellationToken); } } @@ -2183,24 +2235,24 @@ internal PlanApi(JsonRpc rpc, string sessionId) } /// Calls "session.plan.read". - public async Task ReadAsync(CancellationToken cancellationToken = default) + public async Task ReadAsync(CancellationToken cancellationToken = default) { var request = new SessionPlanReadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.read", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.read", [request], cancellationToken); } /// Calls "session.plan.update". - public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) { - var request = new SessionPlanUpdateRequest { SessionId = _sessionId, Content = content }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.update", [request], cancellationToken); + var request = new PlanUpdateRequest { SessionId = _sessionId, Content = content }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.update", [request], cancellationToken); } /// Calls "session.plan.delete". - public async Task DeleteAsync(CancellationToken cancellationToken = default) + public async Task DeleteAsync(CancellationToken cancellationToken = default) { var request = new SessionPlanDeleteRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.delete", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.delete", [request], cancellationToken); } } @@ -2217,24 +2269,24 @@ internal WorkspaceApi(JsonRpc rpc, string sessionId) } /// Calls "session.workspace.listFiles". - public async Task ListFilesAsync(CancellationToken cancellationToken = default) + public async Task ListFilesAsync(CancellationToken cancellationToken = default) { var request = new SessionWorkspaceListFilesRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.listFiles", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.listFiles", [request], cancellationToken); } /// Calls "session.workspace.readFile". - public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default) + public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default) { - var request = new SessionWorkspaceReadFileRequest { SessionId = _sessionId, Path = path }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.readFile", [request], cancellationToken); + var request = new WorkspaceReadFileRequest { SessionId = _sessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.readFile", [request], cancellationToken); } /// Calls "session.workspace.createFile". - public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) + public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) { - var request = new SessionWorkspaceCreateFileRequest { SessionId = _sessionId, Path = path, Content = content }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.createFile", [request], cancellationToken); + var request = new WorkspaceCreateFileRequest { SessionId = _sessionId, Path = path, Content = content }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.createFile", [request], cancellationToken); } } @@ -2252,10 +2304,10 @@ internal FleetApi(JsonRpc rpc, string sessionId) } /// Calls "session.fleet.start". - public async Task StartAsync(string? prompt = null, CancellationToken cancellationToken = default) + public async Task StartAsync(string? prompt = null, CancellationToken cancellationToken = default) { - var request = new SessionFleetStartRequest { SessionId = _sessionId, Prompt = prompt }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.fleet.start", [request], cancellationToken); + var request = new FleetStartRequest { SessionId = _sessionId, Prompt = prompt }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.fleet.start", [request], cancellationToken); } } @@ -2273,38 +2325,38 @@ internal AgentApi(JsonRpc rpc, string sessionId) } /// Calls "session.agent.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.list", [request], cancellationToken); } /// Calls "session.agent.getCurrent". - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentGetCurrentRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.getCurrent", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.getCurrent", [request], cancellationToken); } /// Calls "session.agent.select". - public async Task SelectAsync(string name, CancellationToken cancellationToken = default) + public async Task SelectAsync(string name, CancellationToken cancellationToken = default) { - var request = new SessionAgentSelectRequest { SessionId = _sessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.select", [request], cancellationToken); + var request = new AgentSelectRequest { SessionId = _sessionId, Name = name }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.select", [request], cancellationToken); } /// Calls "session.agent.deselect". - public async Task DeselectAsync(CancellationToken cancellationToken = default) + public async Task DeselectAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentDeselectRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.deselect", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.deselect", [request], cancellationToken); } /// Calls "session.agent.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.reload", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.reload", [request], cancellationToken); } } @@ -2322,31 +2374,31 @@ internal SkillsApi(JsonRpc rpc, string sessionId) } /// Calls "session.skills.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionSkillsListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.list", [request], cancellationToken); } /// Calls "session.skills.enable". - public async Task EnableAsync(string name, CancellationToken cancellationToken = default) + public async Task EnableAsync(string name, CancellationToken cancellationToken = default) { - var request = new SessionSkillsEnableRequest { SessionId = _sessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.enable", [request], cancellationToken); + var request = new SkillsEnableRequest { SessionId = _sessionId, Name = name }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.enable", [request], cancellationToken); } /// Calls "session.skills.disable". - public async Task DisableAsync(string name, CancellationToken cancellationToken = default) + public async Task DisableAsync(string name, CancellationToken cancellationToken = default) { - var request = new SessionSkillsDisableRequest { SessionId = _sessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.disable", [request], cancellationToken); + var request = new SkillsDisableRequest { SessionId = _sessionId, Name = name }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.disable", [request], cancellationToken); } /// Calls "session.skills.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionSkillsReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.reload", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.reload", [request], cancellationToken); } } @@ -2364,31 +2416,31 @@ internal McpApi(JsonRpc rpc, string sessionId) } /// Calls "session.mcp.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.list", [request], cancellationToken); } /// Calls "session.mcp.enable". - public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) + public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) { - var request = new SessionMcpEnableRequest { SessionId = _sessionId, ServerName = serverName }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.enable", [request], cancellationToken); + var request = new McpEnableRequest { SessionId = _sessionId, ServerName = serverName }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.enable", [request], cancellationToken); } /// Calls "session.mcp.disable". - public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) + public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) { - var request = new SessionMcpDisableRequest { SessionId = _sessionId, ServerName = serverName }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.disable", [request], cancellationToken); + var request = new McpDisableRequest { SessionId = _sessionId, ServerName = serverName }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.disable", [request], cancellationToken); } /// Calls "session.mcp.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.reload", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.reload", [request], cancellationToken); } } @@ -2406,10 +2458,10 @@ internal PluginsApi(JsonRpc rpc, string sessionId) } /// Calls "session.plugins.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionPluginsListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plugins.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.plugins.list", [request], cancellationToken); } } @@ -2427,31 +2479,31 @@ internal ExtensionsApi(JsonRpc rpc, string sessionId) } /// Calls "session.extensions.list". - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionExtensionsListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.list", [request], cancellationToken); } /// Calls "session.extensions.enable". - public async Task EnableAsync(string id, CancellationToken cancellationToken = default) + public async Task EnableAsync(string id, CancellationToken cancellationToken = default) { - var request = new SessionExtensionsEnableRequest { SessionId = _sessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.enable", [request], cancellationToken); + var request = new ExtensionsEnableRequest { SessionId = _sessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.enable", [request], cancellationToken); } /// Calls "session.extensions.disable". - public async Task DisableAsync(string id, CancellationToken cancellationToken = default) + public async Task DisableAsync(string id, CancellationToken cancellationToken = default) { - var request = new SessionExtensionsDisableRequest { SessionId = _sessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.disable", [request], cancellationToken); + var request = new ExtensionsDisableRequest { SessionId = _sessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.disable", [request], cancellationToken); } /// Calls "session.extensions.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionExtensionsReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.reload", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.reload", [request], cancellationToken); } } @@ -2468,10 +2520,10 @@ internal ToolsApi(JsonRpc rpc, string sessionId) } /// Calls "session.tools.handlePendingToolCall". - public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) + public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) { - var request = new SessionToolsHandlePendingToolCallRequest { SessionId = _sessionId, RequestId = requestId, Result = result, Error = error }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.tools.handlePendingToolCall", [request], cancellationToken); + var request = new ToolsHandlePendingToolCallRequest { SessionId = _sessionId, RequestId = requestId, Result = result, Error = error }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.tools.handlePendingToolCall", [request], cancellationToken); } } @@ -2488,10 +2540,10 @@ internal CommandsApi(JsonRpc rpc, string sessionId) } /// Calls "session.commands.handlePendingCommand". - public async Task HandlePendingCommandAsync(string requestId, string? error = null, CancellationToken cancellationToken = default) + public async Task HandlePendingCommandAsync(string requestId, string? error = null, CancellationToken cancellationToken = default) { - var request = new SessionCommandsHandlePendingCommandRequest { SessionId = _sessionId, RequestId = requestId, Error = error }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.commands.handlePendingCommand", [request], cancellationToken); + var request = new CommandsHandlePendingCommandRequest { SessionId = _sessionId, RequestId = requestId, Error = error }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.commands.handlePendingCommand", [request], cancellationToken); } } @@ -2508,17 +2560,17 @@ internal UiApi(JsonRpc rpc, string sessionId) } /// Calls "session.ui.elicitation". - public async Task ElicitationAsync(string message, SessionUiElicitationRequestRequestedSchema requestedSchema, CancellationToken cancellationToken = default) + public async Task ElicitationAsync(string message, UiElicitationSchema requestedSchema, CancellationToken cancellationToken = default) { - var request = new SessionUiElicitationRequest { SessionId = _sessionId, Message = message, RequestedSchema = requestedSchema }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.elicitation", [request], cancellationToken); + var request = new UiElicitationRequest { SessionId = _sessionId, Message = message, RequestedSchema = requestedSchema }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.elicitation", [request], cancellationToken); } /// Calls "session.ui.handlePendingElicitation". - public async Task HandlePendingElicitationAsync(string requestId, SessionUiHandlePendingElicitationRequestResult result, CancellationToken cancellationToken = default) + public async Task HandlePendingElicitationAsync(string requestId, UiElicitationResponse result, CancellationToken cancellationToken = default) { - var request = new SessionUiHandlePendingElicitationRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); + var request = new HandlePendingElicitationRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); } } @@ -2535,10 +2587,10 @@ internal PermissionsApi(JsonRpc rpc, string sessionId) } /// Calls "session.permissions.handlePendingPermissionRequest". - public async Task HandlePendingPermissionRequestAsync(string requestId, object result, CancellationToken cancellationToken = default) + public async Task HandlePendingPermissionRequestAsync(string requestId, object result, CancellationToken cancellationToken = default) { - var request = new SessionPermissionsHandlePendingPermissionRequestRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.permissions.handlePendingPermissionRequest", [request], cancellationToken); + var request = new PermissionDecisionRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.permissions.handlePendingPermissionRequest", [request], cancellationToken); } } @@ -2555,17 +2607,17 @@ internal ShellApi(JsonRpc rpc, string sessionId) } /// Calls "session.shell.exec". - public async Task ExecAsync(string command, string? cwd = null, double? timeout = null, CancellationToken cancellationToken = default) + public async Task ExecAsync(string command, string? cwd = null, TimeSpan? timeout = null, CancellationToken cancellationToken = default) { - var request = new SessionShellExecRequest { SessionId = _sessionId, Command = command, Cwd = cwd, Timeout = timeout }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.shell.exec", [request], cancellationToken); + var request = new ShellExecRequest { SessionId = _sessionId, Command = command, Cwd = cwd, Timeout = timeout }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.shell.exec", [request], cancellationToken); } /// Calls "session.shell.kill". - public async Task KillAsync(string processId, SessionShellKillRequestSignal? signal = null, CancellationToken cancellationToken = default) + public async Task KillAsync(string processId, ShellKillSignal? signal = null, CancellationToken cancellationToken = default) { - var request = new SessionShellKillRequest { SessionId = _sessionId, ProcessId = processId, Signal = signal }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.shell.kill", [request], cancellationToken); + var request = new ShellKillRequest { SessionId = _sessionId, ProcessId = processId, Signal = signal }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.shell.kill", [request], cancellationToken); } } @@ -2583,17 +2635,17 @@ internal HistoryApi(JsonRpc rpc, string sessionId) } /// Calls "session.history.compact". - public async Task CompactAsync(CancellationToken cancellationToken = default) + public async Task CompactAsync(CancellationToken cancellationToken = default) { var request = new SessionHistoryCompactRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.compact", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.compact", [request], cancellationToken); } /// Calls "session.history.truncate". - public async Task TruncateAsync(string eventId, CancellationToken cancellationToken = default) + public async Task TruncateAsync(string eventId, CancellationToken cancellationToken = default) { - var request = new SessionHistoryTruncateRequest { SessionId = _sessionId, EventId = eventId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.truncate", [request], cancellationToken); + var request = new HistoryTruncateRequest { SessionId = _sessionId, EventId = eventId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.truncate", [request], cancellationToken); } } @@ -2611,10 +2663,10 @@ internal UsageApi(JsonRpc rpc, string sessionId) } /// Calls "session.usage.getMetrics". - public async Task GetMetricsAsync(CancellationToken cancellationToken = default) + public async Task GetMetricsAsync(CancellationToken cancellationToken = default) { var request = new SessionUsageGetMetricsRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.usage.getMetrics", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.usage.getMetrics", [request], cancellationToken); } } @@ -2622,25 +2674,25 @@ public async Task GetMetricsAsync(CancellationToke public interface ISessionFsHandler { /// Handles "sessionFs.readFile". - Task ReadFileAsync(SessionFsReadFileParams request, CancellationToken cancellationToken = default); + Task ReadFileAsync(SessionFsReadFileRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.writeFile". - Task WriteFileAsync(SessionFsWriteFileParams request, CancellationToken cancellationToken = default); + Task WriteFileAsync(SessionFsWriteFileRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.appendFile". - Task AppendFileAsync(SessionFsAppendFileParams request, CancellationToken cancellationToken = default); + Task AppendFileAsync(SessionFsAppendFileRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.exists". - Task ExistsAsync(SessionFsExistsParams request, CancellationToken cancellationToken = default); + Task ExistsAsync(SessionFsExistsRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.stat". - Task StatAsync(SessionFsStatParams request, CancellationToken cancellationToken = default); + Task StatAsync(SessionFsStatRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.mkdir". - Task MkdirAsync(SessionFsMkdirParams request, CancellationToken cancellationToken = default); + Task MkdirAsync(SessionFsMkdirRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.readdir". - Task ReaddirAsync(SessionFsReaddirParams request, CancellationToken cancellationToken = default); + Task ReaddirAsync(SessionFsReaddirRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.readdirWithTypes". - Task ReaddirWithTypesAsync(SessionFsReaddirWithTypesParams request, CancellationToken cancellationToken = default); + Task ReaddirWithTypesAsync(SessionFsReaddirWithTypesRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.rm". - Task RmAsync(SessionFsRmParams request, CancellationToken cancellationToken = default); + Task RmAsync(SessionFsRmRequest request, CancellationToken cancellationToken = default); /// Handles "sessionFs.rename". - Task RenameAsync(SessionFsRenameParams request, CancellationToken cancellationToken = default); + Task RenameAsync(SessionFsRenameRequest request, CancellationToken cancellationToken = default); } /// Provides all client session API handler groups for a session. @@ -2660,7 +2712,7 @@ public static class ClientSessionApiRegistration /// public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func getHandlers) { - var registerSessionFsReadFileMethod = (Func>)(async (request, cancellationToken) => + var registerSessionFsReadFileMethod = (Func>)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2670,7 +2722,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func)(async (request, cancellationToken) => + var registerSessionFsWriteFileMethod = (Func)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2680,7 +2732,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func)(async (request, cancellationToken) => + var registerSessionFsAppendFileMethod = (Func)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2690,7 +2742,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func>)(async (request, cancellationToken) => + var registerSessionFsExistsMethod = (Func>)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2700,7 +2752,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func>)(async (request, cancellationToken) => + var registerSessionFsStatMethod = (Func>)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2710,7 +2762,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func)(async (request, cancellationToken) => + var registerSessionFsMkdirMethod = (Func)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2720,7 +2772,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func>)(async (request, cancellationToken) => + var registerSessionFsReaddirMethod = (Func>)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2730,7 +2782,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func>)(async (request, cancellationToken) => + var registerSessionFsReaddirWithTypesMethod = (Func>)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2740,7 +2792,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func)(async (request, cancellationToken) => + var registerSessionFsRmMethod = (Func)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2750,7 +2802,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func)(async (request, cancellationToken) => + var registerSessionFsRenameMethod = (Func)(async (request, cancellationToken) => { var handler = getHandlers(request.SessionId).SessionFs; if (handler is null) throw new InvalidOperationException($"No sessionFs handler registered for session: {request.SessionId}"); @@ -2767,14 +2819,48 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, FuncWorking directory and git context at session start. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("context")] - public SessionStartDataContext? Context { get; set; } + public StartContext? Context { get; set; } /// Whether the session was already in use by another client at start time. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1158,7 +1158,7 @@ public partial class SessionResumeData /// Updated working directory and git context at resume time. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("context")] - public SessionResumeDataContext? Context { get; set; } + public ResumeContext? Context { get; set; } /// Whether the session was already in use by another client at resume time. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1308,7 +1308,7 @@ public partial class SessionPlanChangedData { /// The type of operation performed on the plan file. [JsonPropertyName("operation")] - public required SessionPlanChangedDataOperation Operation { get; set; } + public required PlanChangedOperation Operation { get; set; } } /// Workspace file change details including path and operation type. @@ -1320,7 +1320,7 @@ public partial class SessionWorkspaceFileChangedData /// Whether the file was newly created or updated. [JsonPropertyName("operation")] - public required SessionWorkspaceFileChangedDataOperation Operation { get; set; } + public required WorkspaceFileChangedOperation Operation { get; set; } } /// Session handoff metadata including source, context, and repository information. @@ -1332,12 +1332,12 @@ public partial class SessionHandoffData /// Origin type of the session being handed off. [JsonPropertyName("sourceType")] - public required SessionHandoffDataSourceType SourceType { get; set; } + public required HandoffSourceType SourceType { get; set; } /// Repository context for the handed-off session. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("repository")] - public SessionHandoffDataRepository? Repository { get; set; } + public HandoffRepository? Repository { get; set; } /// Additional context information for the handoff. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1413,7 +1413,7 @@ public partial class SessionShutdownData { /// Whether the session ended normally ("routine") or due to a crash/fatal error ("error"). [JsonPropertyName("shutdownType")] - public required SessionShutdownDataShutdownType ShutdownType { get; set; } + public required ShutdownType ShutdownType { get; set; } /// Error description when shutdownType is "error". [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1434,7 +1434,7 @@ public partial class SessionShutdownData /// Aggregate code change metrics for the session. [JsonPropertyName("codeChanges")] - public required SessionShutdownDataCodeChanges CodeChanges { get; set; } + public required ShutdownCodeChanges CodeChanges { get; set; } /// Per-model usage breakdown, keyed by model identifier. [JsonPropertyName("modelMetrics")] @@ -1486,7 +1486,7 @@ public partial class SessionContextChangedData /// Hosting platform type of the repository (github or ado). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("hostType")] - public SessionStartDataContextHostType? HostType { get; set; } + public StartContextHostType? HostType { get; set; } /// Current git branch name. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1614,7 +1614,7 @@ public partial class SessionCompactionCompleteData /// Token usage breakdown for the compaction LLM call. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("compactionTokensUsed")] - public SessionCompactionCompleteDataCompactionTokensUsed? CompactionTokensUsed { get; set; } + public CompactionCompleteCompactionTokensUsed? CompactionTokensUsed { get; set; } /// GitHub request tracing ID (x-github-request-id header) for the compaction LLM call. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1666,7 +1666,7 @@ public partial class UserMessageData /// Files, selections, or GitHub references attached to the message. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("attachments")] - public UserMessageDataAttachmentsItem[]? Attachments { get; set; } + public UserMessageAttachment[]? Attachments { get; set; } /// Origin of this message, used for timeline filtering (e.g., "skill-pdf" for skill-injected messages that should be hidden from the user). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1676,7 +1676,7 @@ public partial class UserMessageData /// The agent mode that was active when this message was sent. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("agentMode")] - public UserMessageDataAgentMode? AgentMode { get; set; } + public UserMessageAgentMode? AgentMode { get; set; } /// CAPI interaction ID for correlating this user message with its turn. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1756,7 +1756,7 @@ public partial class AssistantMessageData /// Tool invocations requested by the assistant in this message. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolRequests")] - public AssistantMessageDataToolRequestsItem[]? ToolRequests { get; set; } + public AssistantMessageToolRequest[]? ToolRequests { get; set; } /// Opaque/encrypted extended thinking data from Anthropic models. Session-bound and stripped on resume. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1851,6 +1851,11 @@ public partial class AssistantUsageData [JsonPropertyName("cacheWriteTokens")] public double? CacheWriteTokens { get; set; } + /// Number of output tokens used for reasoning (e.g., chain-of-thought). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("reasoningTokens")] + public double? ReasoningTokens { get; set; } + /// Model multiplier cost for billing purposes. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cost")] @@ -1899,7 +1904,7 @@ public partial class AssistantUsageData /// Per-request cost and usage data from the CAPI copilot_usage response field. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("copilotUsage")] - public AssistantUsageDataCopilotUsage? CopilotUsage { get; set; } + public AssistantUsageCopilotUsage? CopilotUsage { get; set; } /// Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh"). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2017,12 +2022,12 @@ public partial class ToolExecutionCompleteData /// Tool execution result on success. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("result")] - public ToolExecutionCompleteDataResult? Result { get; set; } + public ToolExecutionCompleteResult? Result { get; set; } /// Error details when the tool execution failed. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("error")] - public ToolExecutionCompleteDataError? Error { get; set; } + public ToolExecutionCompleteError? Error { get; set; } /// Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2228,7 +2233,7 @@ public partial class HookEndData /// Error details when the hook failed. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("error")] - public HookEndDataError? Error { get; set; } + public HookEndError? Error { get; set; } } /// System or developer message content with role and optional template metadata. @@ -2240,7 +2245,7 @@ public partial class SystemMessageData /// Message role: "system" for system prompts, "developer" for developer-injected instructions. [JsonPropertyName("role")] - public required SystemMessageDataRole Role { get; set; } + public required SystemMessageRole Role { get; set; } /// Optional name identifier for the message source. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2250,7 +2255,7 @@ public partial class SystemMessageData /// Metadata about the prompt template and its construction. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("metadata")] - public SystemMessageDataMetadata? Metadata { get; set; } + public SystemMessageMetadata? Metadata { get; set; } } /// System-generated notification for runtime events like background task completion. @@ -2262,7 +2267,7 @@ public partial class SystemNotificationData /// Structured metadata identifying what triggered this notification. [JsonPropertyName("kind")] - public required SystemNotificationDataKind Kind { get; set; } + public required SystemNotification Kind { get; set; } } /// Permission request notification requiring client approval with request details. @@ -2291,7 +2296,7 @@ public partial class PermissionCompletedData /// The result of the permission request. [JsonPropertyName("result")] - public required PermissionCompletedDataResult Result { get; set; } + public required PermissionCompletedResult Result { get; set; } } /// User input request notification with question and optional predefined choices. @@ -2363,12 +2368,12 @@ public partial class ElicitationRequestedData /// Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("mode")] - public ElicitationRequestedDataMode? Mode { get; set; } + public ElicitationRequestedMode? Mode { get; set; } /// JSON Schema describing the form fields to present to the user (form mode only). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("requestedSchema")] - public ElicitationRequestedDataRequestedSchema? RequestedSchema { get; set; } + public ElicitationRequestedSchema? RequestedSchema { get; set; } /// URL to open in the user's browser (url mode only). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2386,7 +2391,7 @@ public partial class ElicitationCompletedData /// The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("action")] - public ElicitationCompletedDataAction? Action { get; set; } + public ElicitationCompletedAction? Action { get; set; } /// The submitted form data when action is 'accept'; keys match the requested schema fields. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2436,7 +2441,7 @@ public partial class McpOauthRequiredData /// Static OAuth client configuration, if the server specifies one. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("staticClientConfig")] - public McpOauthRequiredDataStaticClientConfig? StaticClientConfig { get; set; } + public McpOauthRequiredStaticClientConfig? StaticClientConfig { get; set; } } /// MCP OAuth request completion notification. @@ -2535,7 +2540,7 @@ public partial class CommandsChangedData { /// Current list of registered SDK commands. [JsonPropertyName("commands")] - public required CommandsChangedDataCommandsItem[] Commands { get; set; } + public required CommandsChangedCommand[] Commands { get; set; } } /// Session capability change notification. @@ -2544,7 +2549,7 @@ public partial class CapabilitiesChangedData /// UI capability changes. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("ui")] - public CapabilitiesChangedDataUi? Ui { get; set; } + public CapabilitiesChangedUi? Ui { get; set; } } /// Plan approval request with plan content and available user actions. @@ -2617,7 +2622,7 @@ public partial class SessionSkillsLoadedData { /// Array of resolved skill metadata. [JsonPropertyName("skills")] - public required SessionSkillsLoadedDataSkillsItem[] Skills { get; set; } + public required SkillsLoadedSkill[] Skills { get; set; } } /// Event payload for . @@ -2625,7 +2630,7 @@ public partial class SessionCustomAgentsUpdatedData { /// Array of loaded custom agent metadata. [JsonPropertyName("agents")] - public required SessionCustomAgentsUpdatedDataAgentsItem[] Agents { get; set; } + public required CustomAgentsUpdatedAgent[] Agents { get; set; } /// Non-fatal warnings from agent loading. [JsonPropertyName("warnings")] @@ -2641,7 +2646,7 @@ public partial class SessionMcpServersLoadedData { /// Array of MCP server status summaries. [JsonPropertyName("servers")] - public required SessionMcpServersLoadedDataServersItem[] Servers { get; set; } + public required McpServersLoadedServer[] Servers { get; set; } } /// Event payload for . @@ -2653,7 +2658,7 @@ public partial class SessionMcpServerStatusChangedData /// New connection status: connected, failed, needs-auth, pending, disabled, or not_configured. [JsonPropertyName("status")] - public required SessionMcpServersLoadedDataServersItemStatus Status { get; set; } + public required McpServersLoadedServerStatus Status { get; set; } } /// Event payload for . @@ -2661,12 +2666,12 @@ public partial class SessionExtensionsLoadedData { /// Array of discovered extensions and their status. [JsonPropertyName("extensions")] - public required SessionExtensionsLoadedDataExtensionsItem[] Extensions { get; set; } + public required ExtensionsLoadedExtension[] Extensions { get; set; } } /// Working directory and git context at session start. -/// Nested data type for SessionStartDataContext. -public partial class SessionStartDataContext +/// Nested data type for StartContext. +public partial class StartContext { /// Current working directory path. [JsonPropertyName("cwd")] @@ -2685,7 +2690,7 @@ public partial class SessionStartDataContext /// Hosting platform type of the repository (github or ado). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("hostType")] - public SessionStartDataContextHostType? HostType { get; set; } + public StartContextHostType? HostType { get; set; } /// Current git branch name. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2704,8 +2709,8 @@ public partial class SessionStartDataContext } /// Updated working directory and git context at resume time. -/// Nested data type for SessionResumeDataContext. -public partial class SessionResumeDataContext +/// Nested data type for ResumeContext. +public partial class ResumeContext { /// Current working directory path. [JsonPropertyName("cwd")] @@ -2724,7 +2729,7 @@ public partial class SessionResumeDataContext /// Hosting platform type of the repository (github or ado). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("hostType")] - public SessionStartDataContextHostType? HostType { get; set; } + public StartContextHostType? HostType { get; set; } /// Current git branch name. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2743,8 +2748,8 @@ public partial class SessionResumeDataContext } /// Repository context for the handed-off session. -/// Nested data type for SessionHandoffDataRepository. -public partial class SessionHandoffDataRepository +/// Nested data type for HandoffRepository. +public partial class HandoffRepository { /// Repository owner (user or organization). [JsonPropertyName("owner")] @@ -2761,8 +2766,8 @@ public partial class SessionHandoffDataRepository } /// Aggregate code change metrics for the session. -/// Nested data type for SessionShutdownDataCodeChanges. -public partial class SessionShutdownDataCodeChanges +/// Nested data type for ShutdownCodeChanges. +public partial class ShutdownCodeChanges { /// Total number of lines added during the session. [JsonPropertyName("linesAdded")] @@ -2778,8 +2783,8 @@ public partial class SessionShutdownDataCodeChanges } /// Token usage breakdown for the compaction LLM call. -/// Nested data type for SessionCompactionCompleteDataCompactionTokensUsed. -public partial class SessionCompactionCompleteDataCompactionTokensUsed +/// Nested data type for CompactionCompleteCompactionTokensUsed. +public partial class CompactionCompleteCompactionTokensUsed { /// Input tokens consumed by the compaction LLM call. [JsonPropertyName("input")] @@ -2795,8 +2800,8 @@ public partial class SessionCompactionCompleteDataCompactionTokensUsed } /// Optional line range to scope the attachment to a specific section of the file. -/// Nested data type for UserMessageDataAttachmentsItemFileLineRange. -public partial class UserMessageDataAttachmentsItemFileLineRange +/// Nested data type for UserMessageAttachmentFileLineRange. +public partial class UserMessageAttachmentFileLineRange { /// Start line number (1-based). [JsonPropertyName("start")] @@ -2808,8 +2813,8 @@ public partial class UserMessageDataAttachmentsItemFileLineRange } /// File attachment. -/// The file variant of . -public partial class UserMessageDataAttachmentsItemFile : UserMessageDataAttachmentsItem +/// The file variant of . +public partial class UserMessageAttachmentFile : UserMessageAttachment { /// [JsonIgnore] @@ -2826,12 +2831,12 @@ public partial class UserMessageDataAttachmentsItemFile : UserMessageDataAttachm /// Optional line range to scope the attachment to a specific section of the file. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("lineRange")] - public UserMessageDataAttachmentsItemFileLineRange? LineRange { get; set; } + public UserMessageAttachmentFileLineRange? LineRange { get; set; } } /// Directory attachment. -/// The directory variant of . -public partial class UserMessageDataAttachmentsItemDirectory : UserMessageDataAttachmentsItem +/// The directory variant of . +public partial class UserMessageAttachmentDirectory : UserMessageAttachment { /// [JsonIgnore] @@ -2847,8 +2852,8 @@ public partial class UserMessageDataAttachmentsItemDirectory : UserMessageDataAt } /// Start position of the selection. -/// Nested data type for UserMessageDataAttachmentsItemSelectionSelectionStart. -public partial class UserMessageDataAttachmentsItemSelectionSelectionStart +/// Nested data type for UserMessageAttachmentSelectionDetailsStart. +public partial class UserMessageAttachmentSelectionDetailsStart { /// Start line number (0-based). [JsonPropertyName("line")] @@ -2860,8 +2865,8 @@ public partial class UserMessageDataAttachmentsItemSelectionSelectionStart } /// End position of the selection. -/// Nested data type for UserMessageDataAttachmentsItemSelectionSelectionEnd. -public partial class UserMessageDataAttachmentsItemSelectionSelectionEnd +/// Nested data type for UserMessageAttachmentSelectionDetailsEnd. +public partial class UserMessageAttachmentSelectionDetailsEnd { /// End line number (0-based). [JsonPropertyName("line")] @@ -2873,21 +2878,21 @@ public partial class UserMessageDataAttachmentsItemSelectionSelectionEnd } /// Position range of the selection within the file. -/// Nested data type for UserMessageDataAttachmentsItemSelectionSelection. -public partial class UserMessageDataAttachmentsItemSelectionSelection +/// Nested data type for UserMessageAttachmentSelectionDetails. +public partial class UserMessageAttachmentSelectionDetails { /// Start position of the selection. [JsonPropertyName("start")] - public required UserMessageDataAttachmentsItemSelectionSelectionStart Start { get; set; } + public required UserMessageAttachmentSelectionDetailsStart Start { get; set; } /// End position of the selection. [JsonPropertyName("end")] - public required UserMessageDataAttachmentsItemSelectionSelectionEnd End { get; set; } + public required UserMessageAttachmentSelectionDetailsEnd End { get; set; } } /// Code selection attachment from an editor. -/// The selection variant of . -public partial class UserMessageDataAttachmentsItemSelection : UserMessageDataAttachmentsItem +/// The selection variant of . +public partial class UserMessageAttachmentSelection : UserMessageAttachment { /// [JsonIgnore] @@ -2907,12 +2912,12 @@ public partial class UserMessageDataAttachmentsItemSelection : UserMessageDataAt /// Position range of the selection within the file. [JsonPropertyName("selection")] - public required UserMessageDataAttachmentsItemSelectionSelection Selection { get; set; } + public required UserMessageAttachmentSelectionDetails Selection { get; set; } } /// GitHub issue, pull request, or discussion reference. -/// The github_reference variant of . -public partial class UserMessageDataAttachmentsItemGithubReference : UserMessageDataAttachmentsItem +/// The github_reference variant of . +public partial class UserMessageAttachmentGithubReference : UserMessageAttachment { /// [JsonIgnore] @@ -2928,7 +2933,7 @@ public partial class UserMessageDataAttachmentsItemGithubReference : UserMessage /// Type of GitHub reference. [JsonPropertyName("referenceType")] - public required UserMessageDataAttachmentsItemGithubReferenceReferenceType ReferenceType { get; set; } + public required UserMessageAttachmentGithubReferenceType ReferenceType { get; set; } /// Current state of the referenced item (e.g., open, closed, merged). [JsonPropertyName("state")] @@ -2940,8 +2945,8 @@ public partial class UserMessageDataAttachmentsItemGithubReference : UserMessage } /// Blob attachment with inline base64-encoded data. -/// The blob variant of . -public partial class UserMessageDataAttachmentsItemBlob : UserMessageDataAttachmentsItem +/// The blob variant of . +public partial class UserMessageAttachmentBlob : UserMessageAttachment { /// [JsonIgnore] @@ -2966,12 +2971,12 @@ public partial class UserMessageDataAttachmentsItemBlob : UserMessageDataAttachm [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(UserMessageDataAttachmentsItemFile), "file")] -[JsonDerivedType(typeof(UserMessageDataAttachmentsItemDirectory), "directory")] -[JsonDerivedType(typeof(UserMessageDataAttachmentsItemSelection), "selection")] -[JsonDerivedType(typeof(UserMessageDataAttachmentsItemGithubReference), "github_reference")] -[JsonDerivedType(typeof(UserMessageDataAttachmentsItemBlob), "blob")] -public partial class UserMessageDataAttachmentsItem +[JsonDerivedType(typeof(UserMessageAttachmentFile), "file")] +[JsonDerivedType(typeof(UserMessageAttachmentDirectory), "directory")] +[JsonDerivedType(typeof(UserMessageAttachmentSelection), "selection")] +[JsonDerivedType(typeof(UserMessageAttachmentGithubReference), "github_reference")] +[JsonDerivedType(typeof(UserMessageAttachmentBlob), "blob")] +public partial class UserMessageAttachment { /// The type discriminator. [JsonPropertyName("type")] @@ -2980,8 +2985,8 @@ public partial class UserMessageDataAttachmentsItem /// A tool invocation request from the assistant. -/// Nested data type for AssistantMessageDataToolRequestsItem. -public partial class AssistantMessageDataToolRequestsItem +/// Nested data type for AssistantMessageToolRequest. +public partial class AssistantMessageToolRequest { /// Unique identifier for this tool call. [JsonPropertyName("toolCallId")] @@ -2999,7 +3004,7 @@ public partial class AssistantMessageDataToolRequestsItem /// Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("type")] - public AssistantMessageDataToolRequestsItemType? Type { get; set; } + public AssistantMessageToolRequestType? Type { get; set; } /// Human-readable display title for the tool. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3018,8 +3023,8 @@ public partial class AssistantMessageDataToolRequestsItem } /// Token usage detail for a single billing category. -/// Nested data type for AssistantUsageDataCopilotUsageTokenDetailsItem. -public partial class AssistantUsageDataCopilotUsageTokenDetailsItem +/// Nested data type for AssistantUsageCopilotUsageTokenDetail. +public partial class AssistantUsageCopilotUsageTokenDetail { /// Number of tokens in this billing batch. [JsonPropertyName("batchSize")] @@ -3039,12 +3044,12 @@ public partial class AssistantUsageDataCopilotUsageTokenDetailsItem } /// Per-request cost and usage data from the CAPI copilot_usage response field. -/// Nested data type for AssistantUsageDataCopilotUsage. -public partial class AssistantUsageDataCopilotUsage +/// Nested data type for AssistantUsageCopilotUsage. +public partial class AssistantUsageCopilotUsage { /// Itemized token usage breakdown. [JsonPropertyName("tokenDetails")] - public required AssistantUsageDataCopilotUsageTokenDetailsItem[] TokenDetails { get; set; } + public required AssistantUsageCopilotUsageTokenDetail[] TokenDetails { get; set; } /// Total cost in nano-AIU (AI Units) for this request. [JsonPropertyName("totalNanoAiu")] @@ -3052,8 +3057,8 @@ public partial class AssistantUsageDataCopilotUsage } /// Plain text content block. -/// The text variant of . -public partial class ToolExecutionCompleteDataResultContentsItemText : ToolExecutionCompleteDataResultContentsItem +/// The text variant of . +public partial class ToolExecutionCompleteContentText : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3065,8 +3070,8 @@ public partial class ToolExecutionCompleteDataResultContentsItemText : ToolExecu } /// Terminal/shell output content block with optional exit code and working directory. -/// The terminal variant of . -public partial class ToolExecutionCompleteDataResultContentsItemTerminal : ToolExecutionCompleteDataResultContentsItem +/// The terminal variant of . +public partial class ToolExecutionCompleteContentTerminal : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3088,8 +3093,8 @@ public partial class ToolExecutionCompleteDataResultContentsItemTerminal : ToolE } /// Image content block with base64-encoded data. -/// The image variant of . -public partial class ToolExecutionCompleteDataResultContentsItemImage : ToolExecutionCompleteDataResultContentsItem +/// The image variant of . +public partial class ToolExecutionCompleteContentImage : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3105,8 +3110,8 @@ public partial class ToolExecutionCompleteDataResultContentsItemImage : ToolExec } /// Audio content block with base64-encoded data. -/// The audio variant of . -public partial class ToolExecutionCompleteDataResultContentsItemAudio : ToolExecutionCompleteDataResultContentsItem +/// The audio variant of . +public partial class ToolExecutionCompleteContentAudio : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3122,8 +3127,8 @@ public partial class ToolExecutionCompleteDataResultContentsItemAudio : ToolExec } /// Icon image for a resource. -/// Nested data type for ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItem. -public partial class ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItem +/// Nested data type for ToolExecutionCompleteContentResourceLinkIcon. +public partial class ToolExecutionCompleteContentResourceLinkIcon { /// URL or path to the icon image. [JsonPropertyName("src")] @@ -3142,12 +3147,12 @@ public partial class ToolExecutionCompleteDataResultContentsItemResourceLinkIcon /// Theme variant this icon is intended for. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("theme")] - public ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItemTheme? Theme { get; set; } + public ToolExecutionCompleteContentResourceLinkIconTheme? Theme { get; set; } } /// Resource link content block referencing an external resource. -/// The resource_link variant of . -public partial class ToolExecutionCompleteDataResultContentsItemResourceLink : ToolExecutionCompleteDataResultContentsItem +/// The resource_link variant of . +public partial class ToolExecutionCompleteContentResourceLink : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3156,7 +3161,7 @@ public partial class ToolExecutionCompleteDataResultContentsItemResourceLink : T /// Icons associated with this resource. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("icons")] - public ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItem[]? Icons { get; set; } + public ToolExecutionCompleteContentResourceLinkIcon[]? Icons { get; set; } /// Resource name identifier. [JsonPropertyName("name")] @@ -3188,8 +3193,8 @@ public partial class ToolExecutionCompleteDataResultContentsItemResourceLink : T } /// Embedded resource content block with inline text or binary data. -/// The resource variant of . -public partial class ToolExecutionCompleteDataResultContentsItemResource : ToolExecutionCompleteDataResultContentsItem +/// The resource variant of . +public partial class ToolExecutionCompleteContentResource : ToolExecutionCompleteContent { /// [JsonIgnore] @@ -3205,13 +3210,13 @@ public partial class ToolExecutionCompleteDataResultContentsItemResource : ToolE [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemText), "text")] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemTerminal), "terminal")] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemImage), "image")] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemAudio), "audio")] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemResourceLink), "resource_link")] -[JsonDerivedType(typeof(ToolExecutionCompleteDataResultContentsItemResource), "resource")] -public partial class ToolExecutionCompleteDataResultContentsItem +[JsonDerivedType(typeof(ToolExecutionCompleteContentText), "text")] +[JsonDerivedType(typeof(ToolExecutionCompleteContentTerminal), "terminal")] +[JsonDerivedType(typeof(ToolExecutionCompleteContentImage), "image")] +[JsonDerivedType(typeof(ToolExecutionCompleteContentAudio), "audio")] +[JsonDerivedType(typeof(ToolExecutionCompleteContentResourceLink), "resource_link")] +[JsonDerivedType(typeof(ToolExecutionCompleteContentResource), "resource")] +public partial class ToolExecutionCompleteContent { /// The type discriminator. [JsonPropertyName("type")] @@ -3220,8 +3225,8 @@ public partial class ToolExecutionCompleteDataResultContentsItem /// Tool execution result on success. -/// Nested data type for ToolExecutionCompleteDataResult. -public partial class ToolExecutionCompleteDataResult +/// Nested data type for ToolExecutionCompleteResult. +public partial class ToolExecutionCompleteResult { /// Concise tool result text sent to the LLM for chat completion, potentially truncated for token efficiency. [JsonPropertyName("content")] @@ -3235,12 +3240,12 @@ public partial class ToolExecutionCompleteDataResult /// Structured content blocks (text, images, audio, resources) returned by the tool in their native format. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("contents")] - public ToolExecutionCompleteDataResultContentsItem[]? Contents { get; set; } + public ToolExecutionCompleteContent[]? Contents { get; set; } } /// Error details when the tool execution failed. -/// Nested data type for ToolExecutionCompleteDataError. -public partial class ToolExecutionCompleteDataError +/// Nested data type for ToolExecutionCompleteError. +public partial class ToolExecutionCompleteError { /// Human-readable error message. [JsonPropertyName("message")] @@ -3253,8 +3258,8 @@ public partial class ToolExecutionCompleteDataError } /// Error details when the hook failed. -/// Nested data type for HookEndDataError. -public partial class HookEndDataError +/// Nested data type for HookEndError. +public partial class HookEndError { /// Human-readable error message. [JsonPropertyName("message")] @@ -3267,8 +3272,8 @@ public partial class HookEndDataError } /// Metadata about the prompt template and its construction. -/// Nested data type for SystemMessageDataMetadata. -public partial class SystemMessageDataMetadata +/// Nested data type for SystemMessageMetadata. +public partial class SystemMessageMetadata { /// Version identifier of the prompt template used. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3281,8 +3286,8 @@ public partial class SystemMessageDataMetadata public IDictionary? Variables { get; set; } } -/// The agent_completed variant of . -public partial class SystemNotificationDataKindAgentCompleted : SystemNotificationDataKind +/// The agent_completed variant of . +public partial class SystemNotificationAgentCompleted : SystemNotification { /// [JsonIgnore] @@ -3298,7 +3303,7 @@ public partial class SystemNotificationDataKindAgentCompleted : SystemNotificati /// Whether the agent completed successfully or failed. [JsonPropertyName("status")] - public required SystemNotificationDataKindAgentCompletedStatus Status { get; set; } + public required SystemNotificationAgentCompletedStatus Status { get; set; } /// Human-readable description of the agent task. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3311,8 +3316,8 @@ public partial class SystemNotificationDataKindAgentCompleted : SystemNotificati public string? Prompt { get; set; } } -/// The agent_idle variant of . -public partial class SystemNotificationDataKindAgentIdle : SystemNotificationDataKind +/// The agent_idle variant of . +public partial class SystemNotificationAgentIdle : SystemNotification { /// [JsonIgnore] @@ -3332,8 +3337,8 @@ public partial class SystemNotificationDataKindAgentIdle : SystemNotificationDat public string? Description { get; set; } } -/// The shell_completed variant of . -public partial class SystemNotificationDataKindShellCompleted : SystemNotificationDataKind +/// The shell_completed variant of . +public partial class SystemNotificationShellCompleted : SystemNotification { /// [JsonIgnore] @@ -3354,8 +3359,8 @@ public partial class SystemNotificationDataKindShellCompleted : SystemNotificati public string? Description { get; set; } } -/// The shell_detached_completed variant of . -public partial class SystemNotificationDataKindShellDetachedCompleted : SystemNotificationDataKind +/// The shell_detached_completed variant of . +public partial class SystemNotificationShellDetachedCompleted : SystemNotification { /// [JsonIgnore] @@ -3376,11 +3381,11 @@ public partial class SystemNotificationDataKindShellDetachedCompleted : SystemNo [JsonPolymorphic( TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(SystemNotificationDataKindAgentCompleted), "agent_completed")] -[JsonDerivedType(typeof(SystemNotificationDataKindAgentIdle), "agent_idle")] -[JsonDerivedType(typeof(SystemNotificationDataKindShellCompleted), "shell_completed")] -[JsonDerivedType(typeof(SystemNotificationDataKindShellDetachedCompleted), "shell_detached_completed")] -public partial class SystemNotificationDataKind +[JsonDerivedType(typeof(SystemNotificationAgentCompleted), "agent_completed")] +[JsonDerivedType(typeof(SystemNotificationAgentIdle), "agent_idle")] +[JsonDerivedType(typeof(SystemNotificationShellCompleted), "shell_completed")] +[JsonDerivedType(typeof(SystemNotificationShellDetachedCompleted), "shell_detached_completed")] +public partial class SystemNotification { /// The type discriminator. [JsonPropertyName("type")] @@ -3388,8 +3393,8 @@ public partial class SystemNotificationDataKind } -/// Nested data type for PermissionRequestShellCommandsItem. -public partial class PermissionRequestShellCommandsItem +/// Nested data type for PermissionRequestShellCommand. +public partial class PermissionRequestShellCommand { /// Command identifier (e.g., executable name). [JsonPropertyName("identifier")] @@ -3400,8 +3405,8 @@ public partial class PermissionRequestShellCommandsItem public required bool ReadOnly { get; set; } } -/// Nested data type for PermissionRequestShellPossibleUrlsItem. -public partial class PermissionRequestShellPossibleUrlsItem +/// Nested data type for PermissionRequestShellPossibleUrl. +public partial class PermissionRequestShellPossibleUrl { /// URL that may be accessed by the command. [JsonPropertyName("url")] @@ -3431,7 +3436,7 @@ public partial class PermissionRequestShell : PermissionRequest /// Parsed command identifiers found in the command text. [JsonPropertyName("commands")] - public required PermissionRequestShellCommandsItem[] Commands { get; set; } + public required PermissionRequestShellCommand[] Commands { get; set; } /// File paths that may be read or written by the command. [JsonPropertyName("possiblePaths")] @@ -3439,7 +3444,7 @@ public partial class PermissionRequestShell : PermissionRequest /// URLs that may be accessed by the command. [JsonPropertyName("possibleUrls")] - public required PermissionRequestShellPossibleUrlsItem[] PossibleUrls { get; set; } + public required PermissionRequestShellPossibleUrl[] PossibleUrls { get; set; } /// Whether the command includes a file write redirection (e.g., > or >>). [JsonPropertyName("hasWriteFileRedirection")] @@ -3685,17 +3690,17 @@ public partial class PermissionRequest /// The result of the permission request. -/// Nested data type for PermissionCompletedDataResult. -public partial class PermissionCompletedDataResult +/// Nested data type for PermissionCompletedResult. +public partial class PermissionCompletedResult { /// The outcome of the permission request. [JsonPropertyName("kind")] - public required PermissionCompletedDataResultKind Kind { get; set; } + public required PermissionCompletedKind Kind { get; set; } } /// JSON Schema describing the form fields to present to the user (form mode only). -/// Nested data type for ElicitationRequestedDataRequestedSchema. -public partial class ElicitationRequestedDataRequestedSchema +/// Nested data type for ElicitationRequestedSchema. +public partial class ElicitationRequestedSchema { /// Schema type indicator (always 'object'). [JsonPropertyName("type")] @@ -3712,8 +3717,8 @@ public partial class ElicitationRequestedDataRequestedSchema } /// Static OAuth client configuration, if the server specifies one. -/// Nested data type for McpOauthRequiredDataStaticClientConfig. -public partial class McpOauthRequiredDataStaticClientConfig +/// Nested data type for McpOauthRequiredStaticClientConfig. +public partial class McpOauthRequiredStaticClientConfig { /// OAuth client ID for the server. [JsonPropertyName("clientId")] @@ -3725,8 +3730,8 @@ public partial class McpOauthRequiredDataStaticClientConfig public bool? PublicClient { get; set; } } -/// Nested data type for CommandsChangedDataCommandsItem. -public partial class CommandsChangedDataCommandsItem +/// Nested data type for CommandsChangedCommand. +public partial class CommandsChangedCommand { /// Gets or sets the name value. [JsonPropertyName("name")] @@ -3739,8 +3744,8 @@ public partial class CommandsChangedDataCommandsItem } /// UI capability changes. -/// Nested data type for CapabilitiesChangedDataUi. -public partial class CapabilitiesChangedDataUi +/// Nested data type for CapabilitiesChangedUi. +public partial class CapabilitiesChangedUi { /// Whether elicitation is now supported. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3748,8 +3753,8 @@ public partial class CapabilitiesChangedDataUi public bool? Elicitation { get; set; } } -/// Nested data type for SessionSkillsLoadedDataSkillsItem. -public partial class SessionSkillsLoadedDataSkillsItem +/// Nested data type for SkillsLoadedSkill. +public partial class SkillsLoadedSkill { /// Unique identifier for the skill. [JsonPropertyName("name")] @@ -3777,8 +3782,8 @@ public partial class SessionSkillsLoadedDataSkillsItem public string? Path { get; set; } } -/// Nested data type for SessionCustomAgentsUpdatedDataAgentsItem. -public partial class SessionCustomAgentsUpdatedDataAgentsItem +/// Nested data type for CustomAgentsUpdatedAgent. +public partial class CustomAgentsUpdatedAgent { /// Unique identifier for the agent. [JsonPropertyName("id")] @@ -3814,8 +3819,8 @@ public partial class SessionCustomAgentsUpdatedDataAgentsItem public string? Model { get; set; } } -/// Nested data type for SessionMcpServersLoadedDataServersItem. -public partial class SessionMcpServersLoadedDataServersItem +/// Nested data type for McpServersLoadedServer. +public partial class McpServersLoadedServer { /// Server name (config key). [JsonPropertyName("name")] @@ -3823,7 +3828,7 @@ public partial class SessionMcpServersLoadedDataServersItem /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. [JsonPropertyName("status")] - public required SessionMcpServersLoadedDataServersItemStatus Status { get; set; } + public required McpServersLoadedServerStatus Status { get; set; } /// Configuration source: user, workspace, plugin, or builtin. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3836,8 +3841,8 @@ public partial class SessionMcpServersLoadedDataServersItem public string? Error { get; set; } } -/// Nested data type for SessionExtensionsLoadedDataExtensionsItem. -public partial class SessionExtensionsLoadedDataExtensionsItem +/// Nested data type for ExtensionsLoadedExtension. +public partial class ExtensionsLoadedExtension { /// Source-qualified extension ID (e.g., 'project:my-ext', 'user:auth-helper'). [JsonPropertyName("id")] @@ -3849,16 +3854,16 @@ public partial class SessionExtensionsLoadedDataExtensionsItem /// Discovery source. [JsonPropertyName("source")] - public required SessionExtensionsLoadedDataExtensionsItemSource Source { get; set; } + public required ExtensionsLoadedExtensionSource Source { get; set; } /// Current status: running, disabled, failed, or starting. [JsonPropertyName("status")] - public required SessionExtensionsLoadedDataExtensionsItemStatus Status { get; set; } + public required ExtensionsLoadedExtensionStatus Status { get; set; } } /// Hosting platform type of the repository (github or ado). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionStartDataContextHostType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum StartContextHostType { /// The github variant. [JsonStringEnumMemberName("github")] @@ -3869,8 +3874,8 @@ public enum SessionStartDataContextHostType } /// The type of operation performed on the plan file. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionPlanChangedDataOperation +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum PlanChangedOperation { /// The create variant. [JsonStringEnumMemberName("create")] @@ -3884,8 +3889,8 @@ public enum SessionPlanChangedDataOperation } /// Whether the file was newly created or updated. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionWorkspaceFileChangedDataOperation +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum WorkspaceFileChangedOperation { /// The create variant. [JsonStringEnumMemberName("create")] @@ -3896,8 +3901,8 @@ public enum SessionWorkspaceFileChangedDataOperation } /// Origin type of the session being handed off. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionHandoffDataSourceType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum HandoffSourceType { /// The remote variant. [JsonStringEnumMemberName("remote")] @@ -3908,8 +3913,8 @@ public enum SessionHandoffDataSourceType } /// Whether the session ended normally ("routine") or due to a crash/fatal error ("error"). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionShutdownDataShutdownType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ShutdownType { /// The routine variant. [JsonStringEnumMemberName("routine")] @@ -3920,8 +3925,8 @@ public enum SessionShutdownDataShutdownType } /// Type of GitHub reference. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum UserMessageDataAttachmentsItemGithubReferenceReferenceType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum UserMessageAttachmentGithubReferenceType { /// The issue variant. [JsonStringEnumMemberName("issue")] @@ -3935,8 +3940,8 @@ public enum UserMessageDataAttachmentsItemGithubReferenceReferenceType } /// The agent mode that was active when this message was sent. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum UserMessageDataAgentMode +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum UserMessageAgentMode { /// The interactive variant. [JsonStringEnumMemberName("interactive")] @@ -3953,8 +3958,8 @@ public enum UserMessageDataAgentMode } /// Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum AssistantMessageDataToolRequestsItemType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum AssistantMessageToolRequestType { /// The function variant. [JsonStringEnumMemberName("function")] @@ -3965,8 +3970,8 @@ public enum AssistantMessageDataToolRequestsItemType } /// Theme variant this icon is intended for. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItemTheme +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ToolExecutionCompleteContentResourceLinkIconTheme { /// The light variant. [JsonStringEnumMemberName("light")] @@ -3977,8 +3982,8 @@ public enum ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItemThem } /// Message role: "system" for system prompts, "developer" for developer-injected instructions. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SystemMessageDataRole +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SystemMessageRole { /// The system variant. [JsonStringEnumMemberName("system")] @@ -3989,8 +3994,8 @@ public enum SystemMessageDataRole } /// Whether the agent completed successfully or failed. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SystemNotificationDataKindAgentCompletedStatus +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SystemNotificationAgentCompletedStatus { /// The completed variant. [JsonStringEnumMemberName("completed")] @@ -4025,8 +4030,8 @@ public enum PermissionRequestMemoryDirection } /// The outcome of the permission request. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum PermissionCompletedDataResultKind +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum PermissionCompletedKind { /// The approved variant. [JsonStringEnumMemberName("approved")] @@ -4049,8 +4054,8 @@ public enum PermissionCompletedDataResultKind } /// Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ElicitationRequestedDataMode +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ElicitationRequestedMode { /// The form variant. [JsonStringEnumMemberName("form")] @@ -4061,8 +4066,8 @@ public enum ElicitationRequestedDataMode } /// The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ElicitationCompletedDataAction +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ElicitationCompletedAction { /// The accept variant. [JsonStringEnumMemberName("accept")] @@ -4076,8 +4081,8 @@ public enum ElicitationCompletedDataAction } /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionMcpServersLoadedDataServersItemStatus +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum McpServersLoadedServerStatus { /// The connected variant. [JsonStringEnumMemberName("connected")] @@ -4100,8 +4105,8 @@ public enum SessionMcpServersLoadedDataServersItemStatus } /// Discovery source. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionExtensionsLoadedDataExtensionsItemSource +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ExtensionsLoadedExtensionSource { /// The project variant. [JsonStringEnumMemberName("project")] @@ -4112,8 +4117,8 @@ public enum SessionExtensionsLoadedDataExtensionsItemSource } /// Current status: running, disabled, failed, or starting. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionExtensionsLoadedDataExtensionsItemStatus +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ExtensionsLoadedExtensionStatus { /// The running variant. [JsonStringEnumMemberName("running")] @@ -4139,10 +4144,10 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(AssistantIntentData))] [JsonSerializable(typeof(AssistantIntentEvent))] [JsonSerializable(typeof(AssistantMessageData))] -[JsonSerializable(typeof(AssistantMessageDataToolRequestsItem))] [JsonSerializable(typeof(AssistantMessageDeltaData))] [JsonSerializable(typeof(AssistantMessageDeltaEvent))] [JsonSerializable(typeof(AssistantMessageEvent))] +[JsonSerializable(typeof(AssistantMessageToolRequest))] [JsonSerializable(typeof(AssistantReasoningData))] [JsonSerializable(typeof(AssistantReasoningDeltaData))] [JsonSerializable(typeof(AssistantReasoningDeltaEvent))] @@ -4153,50 +4158,55 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(AssistantTurnEndEvent))] [JsonSerializable(typeof(AssistantTurnStartData))] [JsonSerializable(typeof(AssistantTurnStartEvent))] +[JsonSerializable(typeof(AssistantUsageCopilotUsage))] +[JsonSerializable(typeof(AssistantUsageCopilotUsageTokenDetail))] [JsonSerializable(typeof(AssistantUsageData))] -[JsonSerializable(typeof(AssistantUsageDataCopilotUsage))] -[JsonSerializable(typeof(AssistantUsageDataCopilotUsageTokenDetailsItem))] [JsonSerializable(typeof(AssistantUsageEvent))] [JsonSerializable(typeof(CapabilitiesChangedData))] -[JsonSerializable(typeof(CapabilitiesChangedDataUi))] [JsonSerializable(typeof(CapabilitiesChangedEvent))] +[JsonSerializable(typeof(CapabilitiesChangedUi))] [JsonSerializable(typeof(CommandCompletedData))] [JsonSerializable(typeof(CommandCompletedEvent))] [JsonSerializable(typeof(CommandExecuteData))] [JsonSerializable(typeof(CommandExecuteEvent))] [JsonSerializable(typeof(CommandQueuedData))] [JsonSerializable(typeof(CommandQueuedEvent))] +[JsonSerializable(typeof(CommandsChangedCommand))] [JsonSerializable(typeof(CommandsChangedData))] -[JsonSerializable(typeof(CommandsChangedDataCommandsItem))] [JsonSerializable(typeof(CommandsChangedEvent))] +[JsonSerializable(typeof(CompactionCompleteCompactionTokensUsed))] +[JsonSerializable(typeof(CustomAgentsUpdatedAgent))] [JsonSerializable(typeof(ElicitationCompletedData))] [JsonSerializable(typeof(ElicitationCompletedEvent))] [JsonSerializable(typeof(ElicitationRequestedData))] -[JsonSerializable(typeof(ElicitationRequestedDataRequestedSchema))] [JsonSerializable(typeof(ElicitationRequestedEvent))] +[JsonSerializable(typeof(ElicitationRequestedSchema))] [JsonSerializable(typeof(ExitPlanModeCompletedData))] [JsonSerializable(typeof(ExitPlanModeCompletedEvent))] [JsonSerializable(typeof(ExitPlanModeRequestedData))] [JsonSerializable(typeof(ExitPlanModeRequestedEvent))] +[JsonSerializable(typeof(ExtensionsLoadedExtension))] [JsonSerializable(typeof(ExternalToolCompletedData))] [JsonSerializable(typeof(ExternalToolCompletedEvent))] [JsonSerializable(typeof(ExternalToolRequestedData))] [JsonSerializable(typeof(ExternalToolRequestedEvent))] +[JsonSerializable(typeof(HandoffRepository))] [JsonSerializable(typeof(HookEndData))] -[JsonSerializable(typeof(HookEndDataError))] +[JsonSerializable(typeof(HookEndError))] [JsonSerializable(typeof(HookEndEvent))] [JsonSerializable(typeof(HookStartData))] [JsonSerializable(typeof(HookStartEvent))] [JsonSerializable(typeof(McpOauthCompletedData))] [JsonSerializable(typeof(McpOauthCompletedEvent))] [JsonSerializable(typeof(McpOauthRequiredData))] -[JsonSerializable(typeof(McpOauthRequiredDataStaticClientConfig))] [JsonSerializable(typeof(McpOauthRequiredEvent))] +[JsonSerializable(typeof(McpOauthRequiredStaticClientConfig))] +[JsonSerializable(typeof(McpServersLoadedServer))] [JsonSerializable(typeof(PendingMessagesModifiedData))] [JsonSerializable(typeof(PendingMessagesModifiedEvent))] [JsonSerializable(typeof(PermissionCompletedData))] -[JsonSerializable(typeof(PermissionCompletedDataResult))] [JsonSerializable(typeof(PermissionCompletedEvent))] +[JsonSerializable(typeof(PermissionCompletedResult))] [JsonSerializable(typeof(PermissionRequest))] [JsonSerializable(typeof(PermissionRequestCustomTool))] [JsonSerializable(typeof(PermissionRequestHook))] @@ -4204,12 +4214,13 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(PermissionRequestMemory))] [JsonSerializable(typeof(PermissionRequestRead))] [JsonSerializable(typeof(PermissionRequestShell))] -[JsonSerializable(typeof(PermissionRequestShellCommandsItem))] -[JsonSerializable(typeof(PermissionRequestShellPossibleUrlsItem))] +[JsonSerializable(typeof(PermissionRequestShellCommand))] +[JsonSerializable(typeof(PermissionRequestShellPossibleUrl))] [JsonSerializable(typeof(PermissionRequestUrl))] [JsonSerializable(typeof(PermissionRequestWrite))] [JsonSerializable(typeof(PermissionRequestedData))] [JsonSerializable(typeof(PermissionRequestedEvent))] +[JsonSerializable(typeof(ResumeContext))] [JsonSerializable(typeof(SamplingCompletedData))] [JsonSerializable(typeof(SamplingCompletedEvent))] [JsonSerializable(typeof(SamplingRequestedData))] @@ -4217,23 +4228,19 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SessionBackgroundTasksChangedData))] [JsonSerializable(typeof(SessionBackgroundTasksChangedEvent))] [JsonSerializable(typeof(SessionCompactionCompleteData))] -[JsonSerializable(typeof(SessionCompactionCompleteDataCompactionTokensUsed))] [JsonSerializable(typeof(SessionCompactionCompleteEvent))] [JsonSerializable(typeof(SessionCompactionStartData))] [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))] [JsonSerializable(typeof(SessionExtensionsLoadedData))] -[JsonSerializable(typeof(SessionExtensionsLoadedDataExtensionsItem))] [JsonSerializable(typeof(SessionExtensionsLoadedEvent))] [JsonSerializable(typeof(SessionHandoffData))] -[JsonSerializable(typeof(SessionHandoffDataRepository))] [JsonSerializable(typeof(SessionHandoffEvent))] [JsonSerializable(typeof(SessionIdleData))] [JsonSerializable(typeof(SessionIdleEvent))] @@ -4242,7 +4249,6 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SessionMcpServerStatusChangedData))] [JsonSerializable(typeof(SessionMcpServerStatusChangedEvent))] [JsonSerializable(typeof(SessionMcpServersLoadedData))] -[JsonSerializable(typeof(SessionMcpServersLoadedDataServersItem))] [JsonSerializable(typeof(SessionMcpServersLoadedEvent))] [JsonSerializable(typeof(SessionModeChangedData))] [JsonSerializable(typeof(SessionModeChangedEvent))] @@ -4253,18 +4259,14 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SessionRemoteSteerableChangedData))] [JsonSerializable(typeof(SessionRemoteSteerableChangedEvent))] [JsonSerializable(typeof(SessionResumeData))] -[JsonSerializable(typeof(SessionResumeDataContext))] [JsonSerializable(typeof(SessionResumeEvent))] [JsonSerializable(typeof(SessionShutdownData))] -[JsonSerializable(typeof(SessionShutdownDataCodeChanges))] [JsonSerializable(typeof(SessionShutdownEvent))] [JsonSerializable(typeof(SessionSkillsLoadedData))] -[JsonSerializable(typeof(SessionSkillsLoadedDataSkillsItem))] [JsonSerializable(typeof(SessionSkillsLoadedEvent))] [JsonSerializable(typeof(SessionSnapshotRewindData))] [JsonSerializable(typeof(SessionSnapshotRewindEvent))] [JsonSerializable(typeof(SessionStartData))] -[JsonSerializable(typeof(SessionStartDataContext))] [JsonSerializable(typeof(SessionStartEvent))] [JsonSerializable(typeof(SessionTaskCompleteData))] [JsonSerializable(typeof(SessionTaskCompleteEvent))] @@ -4280,8 +4282,11 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SessionWarningEvent))] [JsonSerializable(typeof(SessionWorkspaceFileChangedData))] [JsonSerializable(typeof(SessionWorkspaceFileChangedEvent))] +[JsonSerializable(typeof(ShutdownCodeChanges))] [JsonSerializable(typeof(SkillInvokedData))] [JsonSerializable(typeof(SkillInvokedEvent))] +[JsonSerializable(typeof(SkillsLoadedSkill))] +[JsonSerializable(typeof(StartContext))] [JsonSerializable(typeof(SubagentCompletedData))] [JsonSerializable(typeof(SubagentCompletedEvent))] [JsonSerializable(typeof(SubagentDeselectedData))] @@ -4293,27 +4298,27 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(SubagentStartedData))] [JsonSerializable(typeof(SubagentStartedEvent))] [JsonSerializable(typeof(SystemMessageData))] -[JsonSerializable(typeof(SystemMessageDataMetadata))] [JsonSerializable(typeof(SystemMessageEvent))] +[JsonSerializable(typeof(SystemMessageMetadata))] +[JsonSerializable(typeof(SystemNotification))] +[JsonSerializable(typeof(SystemNotificationAgentCompleted))] +[JsonSerializable(typeof(SystemNotificationAgentIdle))] [JsonSerializable(typeof(SystemNotificationData))] -[JsonSerializable(typeof(SystemNotificationDataKind))] -[JsonSerializable(typeof(SystemNotificationDataKindAgentCompleted))] -[JsonSerializable(typeof(SystemNotificationDataKindAgentIdle))] -[JsonSerializable(typeof(SystemNotificationDataKindShellCompleted))] -[JsonSerializable(typeof(SystemNotificationDataKindShellDetachedCompleted))] [JsonSerializable(typeof(SystemNotificationEvent))] +[JsonSerializable(typeof(SystemNotificationShellCompleted))] +[JsonSerializable(typeof(SystemNotificationShellDetachedCompleted))] +[JsonSerializable(typeof(ToolExecutionCompleteContent))] +[JsonSerializable(typeof(ToolExecutionCompleteContentAudio))] +[JsonSerializable(typeof(ToolExecutionCompleteContentImage))] +[JsonSerializable(typeof(ToolExecutionCompleteContentResource))] +[JsonSerializable(typeof(ToolExecutionCompleteContentResourceLink))] +[JsonSerializable(typeof(ToolExecutionCompleteContentResourceLinkIcon))] +[JsonSerializable(typeof(ToolExecutionCompleteContentTerminal))] +[JsonSerializable(typeof(ToolExecutionCompleteContentText))] [JsonSerializable(typeof(ToolExecutionCompleteData))] -[JsonSerializable(typeof(ToolExecutionCompleteDataError))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResult))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItem))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemAudio))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemImage))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemResource))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemResourceLink))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemResourceLinkIconsItem))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemTerminal))] -[JsonSerializable(typeof(ToolExecutionCompleteDataResultContentsItemText))] +[JsonSerializable(typeof(ToolExecutionCompleteError))] [JsonSerializable(typeof(ToolExecutionCompleteEvent))] +[JsonSerializable(typeof(ToolExecutionCompleteResult))] [JsonSerializable(typeof(ToolExecutionPartialResultData))] [JsonSerializable(typeof(ToolExecutionPartialResultEvent))] [JsonSerializable(typeof(ToolExecutionProgressData))] @@ -4326,17 +4331,17 @@ public enum SessionExtensionsLoadedDataExtensionsItemStatus [JsonSerializable(typeof(UserInputCompletedEvent))] [JsonSerializable(typeof(UserInputRequestedData))] [JsonSerializable(typeof(UserInputRequestedEvent))] +[JsonSerializable(typeof(UserMessageAttachment))] +[JsonSerializable(typeof(UserMessageAttachmentBlob))] +[JsonSerializable(typeof(UserMessageAttachmentDirectory))] +[JsonSerializable(typeof(UserMessageAttachmentFile))] +[JsonSerializable(typeof(UserMessageAttachmentFileLineRange))] +[JsonSerializable(typeof(UserMessageAttachmentGithubReference))] +[JsonSerializable(typeof(UserMessageAttachmentSelection))] +[JsonSerializable(typeof(UserMessageAttachmentSelectionDetails))] +[JsonSerializable(typeof(UserMessageAttachmentSelectionDetailsEnd))] +[JsonSerializable(typeof(UserMessageAttachmentSelectionDetailsStart))] [JsonSerializable(typeof(UserMessageData))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItem))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemBlob))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemDirectory))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemFile))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemFileLineRange))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemGithubReference))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelection))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelection))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelectionEnd))] -[JsonSerializable(typeof(UserMessageDataAttachmentsItemSelectionSelectionStart))] [JsonSerializable(typeof(UserMessageEvent))] [JsonSerializable(typeof(JsonElement))] internal partial class SessionEventsJsonContext : JsonSerializerContext; \ No newline at end of file diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 2a2778b3c..d150444a2 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -727,7 +727,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str try { var result = await handler(context); - await Rpc.Ui.HandlePendingElicitationAsync(requestId, new SessionUiHandlePendingElicitationRequestResult + await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UiElicitationResponse { Action = result.Action, Content = result.Content @@ -738,9 +738,9 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str // User handler can throw any exception — attempt to cancel so the request doesn't hang. try { - await Rpc.Ui.HandlePendingElicitationAsync(requestId, new SessionUiHandlePendingElicitationRequestResult + await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UiElicitationResponse { - Action = SessionUiElicitationResultAction.Cancel + Action = UiElicitationAction.Cancel }); } catch (Exception innerEx) when (innerEx is IOException or ObjectDisposedException) @@ -771,7 +771,7 @@ private sealed class SessionUiApiImpl(CopilotSession session) : ISessionUiApi public async Task ElicitationAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new SessionUiElicitationRequestRequestedSchema + var schema = new UiElicitationSchema { Type = elicitationParams.RequestedSchema.Type, Properties = elicitationParams.RequestedSchema.Properties, @@ -784,7 +784,7 @@ public async Task ElicitationAsync(ElicitationParams elicitat public async Task ConfirmAsync(string message, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new SessionUiElicitationRequestRequestedSchema + var schema = new UiElicitationSchema { Type = "object", Properties = new Dictionary @@ -794,7 +794,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["confirmed"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == SessionUiElicitationResultAction.Accept + if (result.Action == UiElicitationAction.Accept && result.Content != null && result.Content.TryGetValue("confirmed", out var val)) { @@ -812,7 +812,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat public async Task SelectAsync(string message, string[] options, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new SessionUiElicitationRequestRequestedSchema + var schema = new UiElicitationSchema { Type = "object", Properties = new Dictionary @@ -822,7 +822,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["selection"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == SessionUiElicitationResultAction.Accept + if (result.Action == UiElicitationAction.Accept && result.Content != null && result.Content.TryGetValue("selection", out var val)) { @@ -847,14 +847,14 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat if (options?.Format != null) field["format"] = options.Format; if (options?.Default != null) field["default"] = options.Default; - var schema = new SessionUiElicitationRequestRequestedSchema + var schema = new UiElicitationSchema { Type = "object", Properties = new Dictionary { ["value"] = field }, Required = ["value"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == SessionUiElicitationResultAction.Accept + if (result.Action == UiElicitationAction.Accept && result.Content != null && result.Content.TryGetValue("value", out var val)) { @@ -1135,12 +1135,12 @@ public Task SetModelAsync(string model, CancellationToken cancellationToken = de /// /// /// await session.LogAsync("Build completed successfully"); - /// await session.LogAsync("Disk space low", level: SessionLogRequestLevel.Warning); - /// await session.LogAsync("Connection failed", level: SessionLogRequestLevel.Error); + /// await session.LogAsync("Disk space low", level: SessionLogLevel.Warning); + /// await session.LogAsync("Connection failed", level: SessionLogLevel.Error); /// await session.LogAsync("Temporary status", ephemeral: true); /// /// - public async Task LogAsync(string message, SessionLogRequestLevel? level = null, bool? ephemeral = null, string? url = null, CancellationToken cancellationToken = default) + public async Task LogAsync(string message, SessionLogLevel? level = null, bool? ephemeral = null, string? url = null, CancellationToken cancellationToken = default) { await Rpc.LogAsync(message, level, ephemeral, url, cancellationToken); } @@ -1261,7 +1261,7 @@ internal record SessionDestroyRequest [JsonSerializable(typeof(SendMessageResponse))] [JsonSerializable(typeof(SessionAbortRequest))] [JsonSerializable(typeof(SessionDestroyRequest))] - [JsonSerializable(typeof(UserMessageDataAttachmentsItem))] + [JsonSerializable(typeof(UserMessageAttachment))] [JsonSerializable(typeof(PreToolUseHookInput))] [JsonSerializable(typeof(PreToolUseHookOutput))] [JsonSerializable(typeof(PostToolUseHookInput))] diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 970d44f76..f8af58c9b 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -245,7 +245,7 @@ public sealed class SessionFsConfig /// /// Path conventions used by this filesystem provider. /// - public required SessionFsSetProviderRequestConventions Conventions { get; init; } + public required SessionFsSetProviderConventions Conventions { get; init; } } /// @@ -729,7 +729,7 @@ public class ElicitationResult /// /// User action: "accept" (submitted), "decline" (rejected), or "cancel" (dismissed). /// - public SessionUiElicitationResultAction Action { get; set; } + public UiElicitationAction Action { get; set; } /// /// Form values submitted by the user (present when is Accept). @@ -828,7 +828,7 @@ public class ElicitationContext public ElicitationSchema? RequestedSchema { get; set; } /// Elicitation mode: "form" for structured input, "url" for browser redirect. - public ElicitationRequestedDataMode? Mode { get; set; } + public ElicitationRequestedMode? Mode { get; set; } /// The source that initiated the request (e.g., MCP server name). public string? ElicitationSource { get; set; } diff --git a/dotnet/test/CloneTests.cs b/dotnet/test/CloneTests.cs index dcde71f99..39c42fb25 100644 --- a/dotnet/test/CloneTests.cs +++ b/dotnet/test/CloneTests.cs @@ -203,7 +203,7 @@ public void MessageOptions_Clone_CopiesAllProperties() var original = new MessageOptions { Prompt = "Hello", - Attachments = [new UserMessageDataAttachmentsItemFile { Path = "/test.txt", DisplayName = "test.txt" }], + Attachments = [new UserMessageAttachmentFile { Path = "/test.txt", DisplayName = "test.txt" }], Mode = "chat", }; @@ -219,12 +219,12 @@ public void MessageOptions_Clone_AttachmentsAreIndependent() { var original = new MessageOptions { - Attachments = [new UserMessageDataAttachmentsItemFile { Path = "/test.txt", DisplayName = "test.txt" }], + Attachments = [new UserMessageAttachmentFile { Path = "/test.txt", DisplayName = "test.txt" }], }; var clone = original.Clone(); - clone.Attachments!.Add(new UserMessageDataAttachmentsItemFile { Path = "/other.txt", DisplayName = "other.txt" }); + clone.Attachments!.Add(new UserMessageAttachmentFile { Path = "/other.txt", DisplayName = "other.txt" }); Assert.Single(original.Attachments!); } diff --git a/dotnet/test/ElicitationTests.cs b/dotnet/test/ElicitationTests.cs index f91fe2d19..f110762d8 100644 --- a/dotnet/test/ElicitationTests.cs +++ b/dotnet/test/ElicitationTests.cs @@ -80,7 +80,7 @@ public async Task Sends_RequestElicitation_When_Handler_Provided() OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = SessionUiElicitationResultAction.Accept, + Action = UiElicitationAction.Accept, Content = new Dictionary(), }), }); @@ -99,7 +99,7 @@ public async Task Session_With_ElicitationHandler_Reports_Elicitation_Capability OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = SessionUiElicitationResultAction.Accept, + Action = UiElicitationAction.Accept, Content = new Dictionary(), }), }); @@ -194,17 +194,17 @@ public void ElicitationResult_Types_Are_Properly_Structured() { var result = new ElicitationResult { - Action = SessionUiElicitationResultAction.Accept, + Action = UiElicitationAction.Accept, Content = new Dictionary { ["name"] = "Alice" }, }; - Assert.Equal(SessionUiElicitationResultAction.Accept, result.Action); + Assert.Equal(UiElicitationAction.Accept, result.Action); Assert.NotNull(result.Content); Assert.Equal("Alice", result.Content!["name"]); var declined = new ElicitationResult { - Action = SessionUiElicitationResultAction.Decline, + Action = UiElicitationAction.Decline, }; Assert.Null(declined.Content); } @@ -244,7 +244,7 @@ public void ElicitationContext_Has_All_Properties() ["color"] = new Dictionary { ["type"] = "string", ["enum"] = new[] { "red", "blue" } }, }, }, - Mode = ElicitationRequestedDataMode.Form, + Mode = ElicitationRequestedMode.Form, ElicitationSource = "mcp-server", Url = null, }; @@ -252,7 +252,7 @@ public void ElicitationContext_Has_All_Properties() Assert.Equal("session-42", context.SessionId); Assert.Equal("Pick a color", context.Message); Assert.NotNull(context.RequestedSchema); - Assert.Equal(ElicitationRequestedDataMode.Form, context.Mode); + Assert.Equal(ElicitationRequestedMode.Form, context.Mode); Assert.Equal("mcp-server", context.ElicitationSource); Assert.Null(context.Url); } @@ -262,7 +262,7 @@ public async Task Session_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = SessionUiElicitationResultAction.Cancel, + Action = UiElicitationAction.Cancel, }); var config = new SessionConfig @@ -281,7 +281,7 @@ public void Resume_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = SessionUiElicitationResultAction.Cancel, + Action = UiElicitationAction.Cancel, }); var config = new ResumeSessionConfig diff --git a/dotnet/test/MultiClientCommandsElicitationTests.cs b/dotnet/test/MultiClientCommandsElicitationTests.cs index 3764fd184..cf375c637 100644 --- a/dotnet/test/MultiClientCommandsElicitationTests.cs +++ b/dotnet/test/MultiClientCommandsElicitationTests.cs @@ -175,7 +175,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.SessionUiElicitationResultAction.Accept, + Action = Rpc.UiElicitationAction.Accept, Content = new Dictionary(), }), DisableResume = true, @@ -229,7 +229,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.SessionUiElicitationResultAction.Accept, + Action = Rpc.UiElicitationAction.Accept, Content = new Dictionary(), }), DisableResume = true, diff --git a/dotnet/test/MultiClientTests.cs b/dotnet/test/MultiClientTests.cs index 0f12a3cec..7dbed65fe 100644 --- a/dotnet/test/MultiClientTests.cs +++ b/dotnet/test/MultiClientTests.cs @@ -194,7 +194,7 @@ public async Task One_Client_Approves_Permission_And_Both_See_The_Result() foreach (var evt in client1Events.OfType() .Concat(client2Events.OfType())) { - Assert.Equal(PermissionCompletedDataResultKind.Approved, evt.Data.Result.Kind); + Assert.Equal(PermissionCompletedKind.Approved, evt.Data.Result.Kind); } await session2.DisposeAsync(); @@ -241,7 +241,7 @@ await session1.SendAndWaitAsync(new MessageOptions foreach (var evt in client1Events.OfType() .Concat(client2Events.OfType())) { - Assert.Equal(PermissionCompletedDataResultKind.DeniedInteractivelyByUser, evt.Data.Result.Kind); + Assert.Equal(PermissionCompletedKind.DeniedInteractivelyByUser, evt.Data.Result.Kind); } await session2.DisposeAsync(); diff --git a/dotnet/test/RpcTests.cs b/dotnet/test/RpcTests.cs index e041033bd..640db77b7 100644 --- a/dotnet/test/RpcTests.cs +++ b/dotnet/test/RpcTests.cs @@ -88,19 +88,19 @@ public async Task Should_Get_And_Set_Session_Mode() // Get initial mode (default should be interactive) var initial = await session.Rpc.Mode.GetAsync(); - Assert.Equal(SessionModeGetResultMode.Interactive, initial.Mode); + Assert.Equal(SessionMode.Interactive, initial); // Switch to plan mode - var planResult = await session.Rpc.Mode.SetAsync(SessionModeGetResultMode.Plan); - Assert.Equal(SessionModeGetResultMode.Plan, planResult.Mode); + var planResult = await session.Rpc.Mode.SetAsync(SessionMode.Plan); + Assert.Equal(SessionMode.Plan, planResult); // Verify mode persisted var afterPlan = await session.Rpc.Mode.GetAsync(); - Assert.Equal(SessionModeGetResultMode.Plan, afterPlan.Mode); + Assert.Equal(SessionMode.Plan, afterPlan); // Switch back to interactive - var interactiveResult = await session.Rpc.Mode.SetAsync(SessionModeGetResultMode.Interactive); - Assert.Equal(SessionModeGetResultMode.Interactive, interactiveResult.Mode); + var interactiveResult = await session.Rpc.Mode.SetAsync(SessionMode.Interactive); + Assert.Equal(SessionMode.Interactive, interactiveResult); } [Fact] diff --git a/dotnet/test/SessionEventSerializationTests.cs b/dotnet/test/SessionEventSerializationTests.cs index e7be64422..476867a4d 100644 --- a/dotnet/test/SessionEventSerializationTests.cs +++ b/dotnet/test/SessionEventSerializationTests.cs @@ -24,12 +24,12 @@ public class SessionEventSerializationTests Content = "", ToolRequests = [ - new AssistantMessageDataToolRequestsItem + new AssistantMessageToolRequest { ToolCallId = "call-1", Name = "view", Arguments = ParseJsonElement("""{"path":"README.md"}"""), - Type = AssistantMessageDataToolRequestsItemType.Function, + Type = AssistantMessageToolRequestType.Function, }, ], }, @@ -61,7 +61,7 @@ public class SessionEventSerializationTests { ToolCallId = "call-1", Success = true, - Result = new ToolExecutionCompleteDataResult + Result = new ToolExecutionCompleteResult { Content = "ok", DetailedContent = "ok", @@ -83,11 +83,11 @@ public class SessionEventSerializationTests ParentId = Guid.Parse("88888888-8888-8888-8888-888888888888"), Data = new SessionShutdownData { - ShutdownType = SessionShutdownDataShutdownType.Routine, + ShutdownType = ShutdownType.Routine, TotalPremiumRequests = 1, TotalApiDurationMs = 100, SessionStartTime = 1773609948932, - CodeChanges = new SessionShutdownDataCodeChanges + CodeChanges = new ShutdownCodeChanges { LinesAdded = 1, LinesRemoved = 0, diff --git a/dotnet/test/SessionFsTests.cs b/dotnet/test/SessionFsTests.cs index 202abf323..6e9ed1c8d 100644 --- a/dotnet/test/SessionFsTests.cs +++ b/dotnet/test/SessionFsTests.cs @@ -17,7 +17,7 @@ public class SessionFsTests(E2ETestFixture fixture, ITestOutputHelper output) { InitialCwd = "/", SessionStatePath = "/session-state", - Conventions = SessionFsSetProviderRequestConventions.Posix, + Conventions = SessionFsSetProviderConventions.Posix, }; [Fact] @@ -369,27 +369,27 @@ private static string NormalizeRelativePathSegment(string segment, string paramN private sealed class TestSessionFsHandler(string sessionId, string rootDir) : ISessionFsHandler { - public async Task ReadFileAsync(SessionFsReadFileParams request, CancellationToken cancellationToken = default) + public async Task ReadFileAsync(SessionFsReadFileRequest request, CancellationToken cancellationToken = default) { var content = await File.ReadAllTextAsync(ResolvePath(request.Path), cancellationToken); return new SessionFsReadFileResult { Content = content }; } - public async Task WriteFileAsync(SessionFsWriteFileParams request, CancellationToken cancellationToken = default) + public async Task WriteFileAsync(SessionFsWriteFileRequest request, CancellationToken cancellationToken = default) { var fullPath = ResolvePath(request.Path); Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!); await File.WriteAllTextAsync(fullPath, request.Content, cancellationToken); } - public async Task AppendFileAsync(SessionFsAppendFileParams request, CancellationToken cancellationToken = default) + public async Task AppendFileAsync(SessionFsAppendFileRequest request, CancellationToken cancellationToken = default) { var fullPath = ResolvePath(request.Path); Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!); await File.AppendAllTextAsync(fullPath, request.Content, cancellationToken); } - public Task ExistsAsync(SessionFsExistsParams request, CancellationToken cancellationToken = default) + public Task ExistsAsync(SessionFsExistsRequest request, CancellationToken cancellationToken = default) { var fullPath = ResolvePath(request.Path); return Task.FromResult(new SessionFsExistsResult @@ -398,7 +398,7 @@ public Task ExistsAsync(SessionFsExistsParams request, Ca }); } - public Task StatAsync(SessionFsStatParams request, CancellationToken cancellationToken = default) + public Task StatAsync(SessionFsStatRequest request, CancellationToken cancellationToken = default) { var fullPath = ResolvePath(request.Path); if (File.Exists(fullPath)) @@ -430,13 +430,13 @@ public Task StatAsync(SessionFsStatParams request, Cancella }); } - public Task MkdirAsync(SessionFsMkdirParams request, CancellationToken cancellationToken = default) + public Task MkdirAsync(SessionFsMkdirRequest request, CancellationToken cancellationToken = default) { Directory.CreateDirectory(ResolvePath(request.Path)); return Task.CompletedTask; } - public Task ReaddirAsync(SessionFsReaddirParams request, CancellationToken cancellationToken = default) + public Task ReaddirAsync(SessionFsReaddirRequest request, CancellationToken cancellationToken = default) { var entries = Directory .EnumerateFileSystemEntries(ResolvePath(request.Path)) @@ -448,21 +448,21 @@ public Task ReaddirAsync(SessionFsReaddirParams request, return Task.FromResult(new SessionFsReaddirResult { Entries = entries }); } - public Task ReaddirWithTypesAsync(SessionFsReaddirWithTypesParams request, CancellationToken cancellationToken = default) + public Task ReaddirWithTypesAsync(SessionFsReaddirWithTypesRequest request, CancellationToken cancellationToken = default) { var entries = Directory .EnumerateFileSystemEntries(ResolvePath(request.Path)) - .Select(path => new Entry + .Select(path => new SessionFsReaddirWithTypesEntry { Name = Path.GetFileName(path), - Type = Directory.Exists(path) ? EntryType.Directory : EntryType.File, + Type = Directory.Exists(path) ? SessionFsReaddirWithTypesEntryType.Directory : SessionFsReaddirWithTypesEntryType.File, }) .ToList(); return Task.FromResult(new SessionFsReaddirWithTypesResult { Entries = entries }); } - public Task RmAsync(SessionFsRmParams request, CancellationToken cancellationToken = default) + public Task RmAsync(SessionFsRmRequest request, CancellationToken cancellationToken = default) { var fullPath = ResolvePath(request.Path); @@ -486,7 +486,7 @@ public Task RmAsync(SessionFsRmParams request, CancellationToken cancellationTok throw new FileNotFoundException($"Path does not exist: {request.Path}"); } - public Task RenameAsync(SessionFsRenameParams request, CancellationToken cancellationToken = default) + public Task RenameAsync(SessionFsRenameRequest request, CancellationToken cancellationToken = default) { var src = ResolvePath(request.Src); var dest = ResolvePath(request.Dest); diff --git a/dotnet/test/SessionTests.cs b/dotnet/test/SessionTests.cs index 5200d6de5..59c11a84f 100644 --- a/dotnet/test/SessionTests.cs +++ b/dotnet/test/SessionTests.cs @@ -529,8 +529,8 @@ public async Task Should_Log_Messages_At_Various_Levels() session.On(evt => events.Add(evt)); await session.LogAsync("Info message"); - await session.LogAsync("Warning message", level: SessionLogRequestLevel.Warning); - await session.LogAsync("Error message", level: SessionLogRequestLevel.Error); + await session.LogAsync("Warning message", level: SessionLogLevel.Warning); + await session.LogAsync("Error message", level: SessionLogLevel.Error); await session.LogAsync("Ephemeral message", ephemeral: true); // Poll until all 4 notification events arrive @@ -618,7 +618,7 @@ await session.SendAndWaitAsync(new MessageOptions Prompt = "Describe this image", Attachments = [ - new UserMessageDataAttachmentsItemBlob + new UserMessageAttachmentBlob { Data = pngBase64, MimeType = "image/png", diff --git a/go/client.go b/go/client.go index ebea33209..db8438041 100644 --- a/go/client.go +++ b/go/client.go @@ -63,7 +63,7 @@ func validateSessionFsConfig(config *SessionFsConfig) error { if config.SessionStatePath == "" { return errors.New("SessionFs.SessionStatePath is required") } - if config.Conventions != rpc.ConventionsPosix && config.Conventions != rpc.ConventionsWindows { + if config.Conventions != rpc.SessionFSSetProviderConventionsPosix && config.Conventions != rpc.SessionFSSetProviderConventionsWindows { return errors.New("SessionFs.Conventions must be either 'posix' or 'windows'") } return nil @@ -330,7 +330,7 @@ func (c *Client) Start(ctx context.Context) error { // If a session filesystem provider was configured, register it. if c.options.SessionFs != nil { - _, err := c.RPC.SessionFs.SetProvider(ctx, &rpc.SessionFSSetProviderParams{ + _, err := c.RPC.SessionFs.SetProvider(ctx, &rpc.SessionFSSetProviderRequest{ InitialCwd: c.options.SessionFs.InitialCwd, SessionStatePath: c.options.SessionFs.SessionStatePath, Conventions: c.options.SessionFs.Conventions, diff --git a/go/client_test.go b/go/client_test.go index 1b88eda20..091c31726 100644 --- a/go/client_test.go +++ b/go/client_test.go @@ -241,7 +241,7 @@ func TestClient_SessionFsConfig(t *testing.T) { NewClient(&ClientOptions{ SessionFs: &SessionFsConfig{ SessionStatePath: "/session-state", - Conventions: rpc.ConventionsPosix, + Conventions: rpc.SessionFSSetProviderConventionsPosix, }, }) }) @@ -261,7 +261,7 @@ func TestClient_SessionFsConfig(t *testing.T) { NewClient(&ClientOptions{ SessionFs: &SessionFsConfig{ InitialCwd: "/", - Conventions: rpc.ConventionsPosix, + Conventions: rpc.SessionFSSetProviderConventionsPosix, }, }) }) diff --git a/go/generated_session_events.go b/go/generated_session_events.go index 1bd2e8959..3c64be8f7 100644 --- a/go/generated_session_events.go +++ b/go/generated_session_events.go @@ -637,7 +637,7 @@ type SessionStartData struct { // Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh") ReasoningEffort *string `json:"reasoningEffort,omitempty"` // Working directory and git context at session start - Context *SessionStartDataContext `json:"context,omitempty"` + Context *StartContext `json:"context,omitempty"` // Whether the session was already in use by another client at start time AlreadyInUse *bool `json:"alreadyInUse,omitempty"` // Whether this session supports remote steering via Mission Control @@ -657,7 +657,7 @@ type SessionResumeData struct { // Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh") ReasoningEffort *string `json:"reasoningEffort,omitempty"` // Updated working directory and git context at resume time - Context *SessionResumeDataContext `json:"context,omitempty"` + Context *ResumeContext `json:"context,omitempty"` // Whether the session was already in use by another client at resume time AlreadyInUse *bool `json:"alreadyInUse,omitempty"` // Whether this session supports remote steering via Mission Control @@ -759,7 +759,7 @@ func (*SessionModeChangedData) sessionEventData() {} // Plan file operation details indicating what changed type SessionPlanChangedData struct { // The type of operation performed on the plan file - Operation SessionPlanChangedDataOperation `json:"operation"` + Operation PlanChangedOperation `json:"operation"` } func (*SessionPlanChangedData) sessionEventData() {} @@ -769,7 +769,7 @@ type SessionWorkspaceFileChangedData struct { // Relative path within the session workspace files directory Path string `json:"path"` // Whether the file was newly created or updated - Operation SessionWorkspaceFileChangedDataOperation `json:"operation"` + Operation WorkspaceFileChangedOperation `json:"operation"` } func (*SessionWorkspaceFileChangedData) sessionEventData() {} @@ -779,9 +779,9 @@ type SessionHandoffData struct { // ISO 8601 timestamp when the handoff occurred HandoffTime time.Time `json:"handoffTime"` // Origin type of the session being handed off - SourceType SessionHandoffDataSourceType `json:"sourceType"` + SourceType HandoffSourceType `json:"sourceType"` // Repository context for the handed-off session - Repository *SessionHandoffDataRepository `json:"repository,omitempty"` + Repository *HandoffRepository `json:"repository,omitempty"` // Additional context information for the handoff Context *string `json:"context,omitempty"` // Summary of the work done in the source session @@ -829,7 +829,7 @@ func (*SessionSnapshotRewindData) sessionEventData() {} // Session termination metrics including usage statistics, code changes, and shutdown reason type SessionShutdownData struct { // Whether the session ended normally ("routine") or due to a crash/fatal error ("error") - ShutdownType SessionShutdownDataShutdownType `json:"shutdownType"` + ShutdownType ShutdownType `json:"shutdownType"` // Error description when shutdownType is "error" ErrorReason *string `json:"errorReason,omitempty"` // Total number of premium API requests used during the session @@ -839,9 +839,9 @@ type SessionShutdownData struct { // Unix timestamp (milliseconds) when the session started SessionStartTime float64 `json:"sessionStartTime"` // Aggregate code change metrics for the session - CodeChanges SessionShutdownDataCodeChanges `json:"codeChanges"` + CodeChanges ShutdownCodeChanges `json:"codeChanges"` // Per-model usage breakdown, keyed by model identifier - ModelMetrics map[string]SessionShutdownDataModelMetricsValue `json:"modelMetrics"` + ModelMetrics map[string]ShutdownModelMetric `json:"modelMetrics"` // Model that was selected at the time of shutdown CurrentModel *string `json:"currentModel,omitempty"` // Total tokens in context window at shutdown @@ -865,7 +865,7 @@ type SessionContextChangedData struct { // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) Repository *string `json:"repository,omitempty"` // Hosting platform type of the repository (github or ado) - HostType *SessionStartDataContextHostType `json:"hostType,omitempty"` + HostType *StartContextHostType `json:"hostType,omitempty"` // Current git branch name Branch *string `json:"branch,omitempty"` // Head commit of current git branch at session start time @@ -931,7 +931,7 @@ type SessionCompactionCompleteData struct { // File path where the checkpoint was stored CheckpointPath *string `json:"checkpointPath,omitempty"` // Token usage breakdown for the compaction LLM call - CompactionTokensUsed *SessionCompactionCompleteDataCompactionTokensUsed `json:"compactionTokensUsed,omitempty"` + CompactionTokensUsed *CompactionCompleteCompactionTokensUsed `json:"compactionTokensUsed,omitempty"` // GitHub request tracing ID (x-github-request-id header) for the compaction LLM call RequestID *string `json:"requestId,omitempty"` // Token count from system message(s) after compaction @@ -961,11 +961,11 @@ type UserMessageData struct { // Transformed version of the message sent to the model, with XML wrapping, timestamps, and other augmentations for prompt caching TransformedContent *string `json:"transformedContent,omitempty"` // Files, selections, or GitHub references attached to the message - Attachments []UserMessageDataAttachmentsItem `json:"attachments,omitempty"` + Attachments []UserMessageAttachment `json:"attachments,omitempty"` // Origin of this message, used for timeline filtering (e.g., "skill-pdf" for skill-injected messages that should be hidden from the user) Source *string `json:"source,omitempty"` // The agent mode that was active when this message was sent - AgentMode *UserMessageDataAgentMode `json:"agentMode,omitempty"` + AgentMode *UserMessageAgentMode `json:"agentMode,omitempty"` // CAPI interaction ID for correlating this user message with its turn InteractionID *string `json:"interactionId,omitempty"` } @@ -1031,7 +1031,7 @@ type AssistantMessageData struct { // The assistant's text response content Content string `json:"content"` // Tool invocations requested by the assistant in this message - ToolRequests []AssistantMessageDataToolRequestsItem `json:"toolRequests,omitempty"` + ToolRequests []AssistantMessageToolRequest `json:"toolRequests,omitempty"` // Opaque/encrypted extended thinking data from Anthropic models. Session-bound and stripped on resume. ReasoningOpaque *string `json:"reasoningOpaque,omitempty"` // Readable reasoning text from the model's extended thinking @@ -1084,6 +1084,8 @@ type AssistantUsageData struct { CacheReadTokens *float64 `json:"cacheReadTokens,omitempty"` // Number of tokens written to prompt cache CacheWriteTokens *float64 `json:"cacheWriteTokens,omitempty"` + // Number of output tokens used for reasoning (e.g., chain-of-thought) + ReasoningTokens *float64 `json:"reasoningTokens,omitempty"` // Model multiplier cost for billing purposes Cost *float64 `json:"cost,omitempty"` // Duration of the API call in milliseconds @@ -1101,9 +1103,9 @@ type AssistantUsageData struct { // Parent tool call ID when this usage originates from a sub-agent ParentToolCallID *string `json:"parentToolCallId,omitempty"` // Per-quota resource usage snapshots, keyed by quota identifier - QuotaSnapshots map[string]AssistantUsageDataQuotaSnapshotsValue `json:"quotaSnapshots,omitempty"` + QuotaSnapshots map[string]AssistantUsageQuotaSnapshot `json:"quotaSnapshots,omitempty"` // Per-request cost and usage data from the CAPI copilot_usage response field - CopilotUsage *AssistantUsageDataCopilotUsage `json:"copilotUsage,omitempty"` + CopilotUsage *AssistantUsageCopilotUsage `json:"copilotUsage,omitempty"` // Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh") ReasoningEffort *string `json:"reasoningEffort,omitempty"` } @@ -1181,9 +1183,9 @@ type ToolExecutionCompleteData struct { // Whether this tool call was explicitly requested by the user rather than the assistant IsUserRequested *bool `json:"isUserRequested,omitempty"` // Tool execution result on success - Result *ToolExecutionCompleteDataResult `json:"result,omitempty"` + Result *ToolExecutionCompleteResult `json:"result,omitempty"` // Error details when the tool execution failed - Error *ToolExecutionCompleteDataError `json:"error,omitempty"` + Error *ToolExecutionCompleteError `json:"error,omitempty"` // Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts) ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` // Tool call ID of the parent tool invocation when this event originates from a sub-agent @@ -1309,7 +1311,7 @@ type HookEndData struct { // Whether the hook completed successfully Success bool `json:"success"` // Error details when the hook failed - Error *HookEndDataError `json:"error,omitempty"` + Error *HookEndError `json:"error,omitempty"` } func (*HookEndData) sessionEventData() {} @@ -1319,11 +1321,11 @@ type SystemMessageData struct { // The system or developer prompt text Content string `json:"content"` // Message role: "system" for system prompts, "developer" for developer-injected instructions - Role SystemMessageDataRole `json:"role"` + Role SystemMessageRole `json:"role"` // Optional name identifier for the message source Name *string `json:"name,omitempty"` // Metadata about the prompt template and its construction - Metadata *SystemMessageDataMetadata `json:"metadata,omitempty"` + Metadata *SystemMessageMetadata `json:"metadata,omitempty"` } func (*SystemMessageData) sessionEventData() {} @@ -1333,7 +1335,7 @@ type SystemNotificationData struct { // The notification text, typically wrapped in XML tags Content string `json:"content"` // Structured metadata identifying what triggered this notification - Kind SystemNotificationDataKind `json:"kind"` + Kind SystemNotification `json:"kind"` } func (*SystemNotificationData) sessionEventData() {} @@ -1343,7 +1345,7 @@ type PermissionRequestedData struct { // Unique identifier for this permission request; used to respond via session.respondToPermission() RequestID string `json:"requestId"` // Details of the permission being requested - PermissionRequest PermissionRequestedDataPermissionRequest `json:"permissionRequest"` + PermissionRequest PermissionRequest `json:"permissionRequest"` // When true, this permission was already resolved by a permissionRequest hook and requires no client action ResolvedByHook *bool `json:"resolvedByHook,omitempty"` } @@ -1355,7 +1357,7 @@ type PermissionCompletedData struct { // Request ID of the resolved permission request; clients should dismiss any UI for this request RequestID string `json:"requestId"` // The result of the permission request - Result PermissionCompletedDataResult `json:"result"` + Result PermissionCompletedResult `json:"result"` } func (*PermissionCompletedData) sessionEventData() {} @@ -1399,9 +1401,9 @@ type ElicitationRequestedData struct { // Message describing what information is needed from the user Message string `json:"message"` // Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. - Mode *ElicitationRequestedDataMode `json:"mode,omitempty"` + Mode *ElicitationRequestedMode `json:"mode,omitempty"` // JSON Schema describing the form fields to present to the user (form mode only) - RequestedSchema *ElicitationRequestedDataRequestedSchema `json:"requestedSchema,omitempty"` + RequestedSchema *ElicitationRequestedSchema `json:"requestedSchema,omitempty"` // URL to open in the user's browser (url mode only) URL *string `json:"url,omitempty"` } @@ -1413,7 +1415,7 @@ type ElicitationCompletedData struct { // Request ID of the resolved elicitation request; clients should dismiss any UI for this request RequestID string `json:"requestId"` // The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) - Action *ElicitationCompletedDataAction `json:"action,omitempty"` + Action *ElicitationCompletedAction `json:"action,omitempty"` // The submitted form data when action is 'accept'; keys match the requested schema fields Content map[string]any `json:"content,omitempty"` } @@ -1449,7 +1451,7 @@ type McpOauthRequiredData struct { // URL of the MCP server that requires OAuth ServerURL string `json:"serverUrl"` // Static OAuth client configuration, if the server specifies one - StaticClientConfig *McpOauthRequiredDataStaticClientConfig `json:"staticClientConfig,omitempty"` + StaticClientConfig *McpOauthRequiredStaticClientConfig `json:"staticClientConfig,omitempty"` } func (*McpOauthRequiredData) sessionEventData() {} @@ -1525,7 +1527,7 @@ func (*CommandCompletedData) sessionEventData() {} // SDK command registration change notification type CommandsChangedData struct { // Current list of registered SDK commands - Commands []CommandsChangedDataCommandsItem `json:"commands"` + Commands []CommandsChangedCommand `json:"commands"` } func (*CommandsChangedData) sessionEventData() {} @@ -1533,7 +1535,7 @@ func (*CommandsChangedData) sessionEventData() {} // Session capability change notification type CapabilitiesChangedData struct { // UI capability changes - UI *CapabilitiesChangedDataUI `json:"ui,omitempty"` + UI *CapabilitiesChangedUi `json:"ui,omitempty"` } func (*CapabilitiesChangedData) sessionEventData() {} @@ -1586,7 +1588,7 @@ func (*SessionBackgroundTasksChangedData) sessionEventData() {} // SessionSkillsLoadedData holds the payload for session.skills_loaded events. type SessionSkillsLoadedData struct { // Array of resolved skill metadata - Skills []SessionSkillsLoadedDataSkillsItem `json:"skills"` + Skills []SkillsLoadedSkill `json:"skills"` } func (*SessionSkillsLoadedData) sessionEventData() {} @@ -1594,7 +1596,7 @@ func (*SessionSkillsLoadedData) sessionEventData() {} // SessionCustomAgentsUpdatedData holds the payload for session.custom_agents_updated events. type SessionCustomAgentsUpdatedData struct { // Array of loaded custom agent metadata - Agents []SessionCustomAgentsUpdatedDataAgentsItem `json:"agents"` + Agents []CustomAgentsUpdatedAgent `json:"agents"` // Non-fatal warnings from agent loading Warnings []string `json:"warnings"` // Fatal errors from agent loading @@ -1606,7 +1608,7 @@ func (*SessionCustomAgentsUpdatedData) sessionEventData() {} // SessionMcpServersLoadedData holds the payload for session.mcp_servers_loaded events. type SessionMcpServersLoadedData struct { // Array of MCP server status summaries - Servers []SessionMcpServersLoadedDataServersItem `json:"servers"` + Servers []McpServersLoadedServer `json:"servers"` } func (*SessionMcpServersLoadedData) sessionEventData() {} @@ -1616,7 +1618,7 @@ type SessionMcpServerStatusChangedData struct { // Name of the MCP server whose status changed ServerName string `json:"serverName"` // New connection status: connected, failed, needs-auth, pending, disabled, or not_configured - Status SessionMcpServersLoadedDataServersItemStatus `json:"status"` + Status McpServersLoadedServerStatus `json:"status"` } func (*SessionMcpServerStatusChangedData) sessionEventData() {} @@ -1624,13 +1626,13 @@ func (*SessionMcpServerStatusChangedData) sessionEventData() {} // SessionExtensionsLoadedData holds the payload for session.extensions_loaded events. type SessionExtensionsLoadedData struct { // Array of discovered extensions and their status - Extensions []SessionExtensionsLoadedDataExtensionsItem `json:"extensions"` + Extensions []ExtensionsLoadedExtension `json:"extensions"` } func (*SessionExtensionsLoadedData) sessionEventData() {} // Working directory and git context at session start -type SessionStartDataContext struct { +type StartContext struct { // Current working directory path Cwd string `json:"cwd"` // Root directory of the git repository, resolved via git rev-parse @@ -1638,7 +1640,7 @@ type SessionStartDataContext struct { // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) Repository *string `json:"repository,omitempty"` // Hosting platform type of the repository (github or ado) - HostType *SessionStartDataContextHostType `json:"hostType,omitempty"` + HostType *StartContextHostType `json:"hostType,omitempty"` // Current git branch name Branch *string `json:"branch,omitempty"` // Head commit of current git branch at session start time @@ -1648,7 +1650,7 @@ type SessionStartDataContext struct { } // Updated working directory and git context at resume time -type SessionResumeDataContext struct { +type ResumeContext struct { // Current working directory path Cwd string `json:"cwd"` // Root directory of the git repository, resolved via git rev-parse @@ -1656,7 +1658,7 @@ type SessionResumeDataContext struct { // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) Repository *string `json:"repository,omitempty"` // Hosting platform type of the repository (github or ado) - HostType *SessionStartDataContextHostType `json:"hostType,omitempty"` + HostType *StartContextHostType `json:"hostType,omitempty"` // Current git branch name Branch *string `json:"branch,omitempty"` // Head commit of current git branch at session start time @@ -1666,7 +1668,7 @@ type SessionResumeDataContext struct { } // Repository context for the handed-off session -type SessionHandoffDataRepository struct { +type HandoffRepository struct { // Repository owner (user or organization) Owner string `json:"owner"` // Repository name @@ -1676,7 +1678,7 @@ type SessionHandoffDataRepository struct { } // Aggregate code change metrics for the session -type SessionShutdownDataCodeChanges struct { +type ShutdownCodeChanges struct { // Total number of lines added during the session LinesAdded float64 `json:"linesAdded"` // Total number of lines removed during the session @@ -1686,7 +1688,7 @@ type SessionShutdownDataCodeChanges struct { } // Request count and cost metrics -type SessionShutdownDataModelMetricsValueRequests struct { +type ShutdownModelMetricRequests struct { // Total number of API requests made to this model Count float64 `json:"count"` // Cumulative cost multiplier for requests to this model @@ -1694,7 +1696,7 @@ type SessionShutdownDataModelMetricsValueRequests struct { } // Token usage breakdown -type SessionShutdownDataModelMetricsValueUsage struct { +type ShutdownModelMetricUsage struct { // Total input tokens consumed across all requests to this model InputTokens float64 `json:"inputTokens"` // Total output tokens produced across all requests to this model @@ -1703,17 +1705,19 @@ type SessionShutdownDataModelMetricsValueUsage struct { CacheReadTokens float64 `json:"cacheReadTokens"` // Total tokens written to prompt cache across all requests CacheWriteTokens float64 `json:"cacheWriteTokens"` + // Total reasoning tokens produced across all requests to this model + ReasoningTokens *float64 `json:"reasoningTokens,omitempty"` } -type SessionShutdownDataModelMetricsValue struct { +type ShutdownModelMetric struct { // Request count and cost metrics - Requests SessionShutdownDataModelMetricsValueRequests `json:"requests"` + Requests ShutdownModelMetricRequests `json:"requests"` // Token usage breakdown - Usage SessionShutdownDataModelMetricsValueUsage `json:"usage"` + Usage ShutdownModelMetricUsage `json:"usage"` } // Token usage breakdown for the compaction LLM call -type SessionCompactionCompleteDataCompactionTokensUsed struct { +type CompactionCompleteCompactionTokensUsed struct { // Input tokens consumed by the compaction LLM call Input float64 `json:"input"` // Output tokens produced by the compaction LLM call @@ -1723,7 +1727,7 @@ type SessionCompactionCompleteDataCompactionTokensUsed struct { } // Optional line range to scope the attachment to a specific section of the file -type UserMessageDataAttachmentsItemLineRange struct { +type UserMessageAttachmentFileLineRange struct { // Start line number (1-based) Start float64 `json:"start"` // End line number (1-based, inclusive) @@ -1731,7 +1735,7 @@ type UserMessageDataAttachmentsItemLineRange struct { } // Start position of the selection -type UserMessageDataAttachmentsItemSelectionStart struct { +type UserMessageAttachmentSelectionDetailsStart struct { // Start line number (0-based) Line float64 `json:"line"` // Start character offset within the line (0-based) @@ -1739,7 +1743,7 @@ type UserMessageDataAttachmentsItemSelectionStart struct { } // End position of the selection -type UserMessageDataAttachmentsItemSelectionEnd struct { +type UserMessageAttachmentSelectionDetailsEnd struct { // End line number (0-based) Line float64 `json:"line"` // End character offset within the line (0-based) @@ -1747,35 +1751,35 @@ type UserMessageDataAttachmentsItemSelectionEnd struct { } // Position range of the selection within the file -type UserMessageDataAttachmentsItemSelection struct { +type UserMessageAttachmentSelectionDetails struct { // Start position of the selection - Start UserMessageDataAttachmentsItemSelectionStart `json:"start"` + Start UserMessageAttachmentSelectionDetailsStart `json:"start"` // End position of the selection - End UserMessageDataAttachmentsItemSelectionEnd `json:"end"` + End UserMessageAttachmentSelectionDetailsEnd `json:"end"` } // A user message attachment — a file, directory, code selection, blob, or GitHub reference -type UserMessageDataAttachmentsItem struct { +type UserMessageAttachment struct { // Type discriminator - Type UserMessageDataAttachmentsItemType `json:"type"` + Type UserMessageAttachmentType `json:"type"` // Absolute file path Path *string `json:"path,omitempty"` // User-facing display name for the attachment DisplayName *string `json:"displayName,omitempty"` // Optional line range to scope the attachment to a specific section of the file - LineRange *UserMessageDataAttachmentsItemLineRange `json:"lineRange,omitempty"` + LineRange *UserMessageAttachmentFileLineRange `json:"lineRange,omitempty"` // Absolute path to the file containing the selection FilePath *string `json:"filePath,omitempty"` // The selected text content Text *string `json:"text,omitempty"` // Position range of the selection within the file - Selection *UserMessageDataAttachmentsItemSelection `json:"selection,omitempty"` + Selection *UserMessageAttachmentSelectionDetails `json:"selection,omitempty"` // Issue, pull request, or discussion number Number *float64 `json:"number,omitempty"` // Title of the referenced item Title *string `json:"title,omitempty"` // Type of GitHub reference - ReferenceType *UserMessageDataAttachmentsItemReferenceType `json:"referenceType,omitempty"` + ReferenceType *UserMessageAttachmentGithubReferenceType `json:"referenceType,omitempty"` // Current state of the referenced item (e.g., open, closed, merged) State *string `json:"state,omitempty"` // URL to the referenced item on GitHub @@ -1787,7 +1791,7 @@ type UserMessageDataAttachmentsItem struct { } // A tool invocation request from the assistant -type AssistantMessageDataToolRequestsItem struct { +type AssistantMessageToolRequest struct { // Unique identifier for this tool call ToolCallID string `json:"toolCallId"` // Name of the tool being invoked @@ -1795,7 +1799,7 @@ type AssistantMessageDataToolRequestsItem struct { // Arguments to pass to the tool, format depends on the tool Arguments any `json:"arguments,omitempty"` // Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. - Type *AssistantMessageDataToolRequestsItemType `json:"type,omitempty"` + Type *AssistantMessageToolRequestType `json:"type,omitempty"` // Human-readable display title for the tool ToolTitle *string `json:"toolTitle,omitempty"` // Name of the MCP server hosting this tool, when the tool is an MCP tool @@ -1804,7 +1808,7 @@ type AssistantMessageDataToolRequestsItem struct { IntentionSummary *string `json:"intentionSummary,omitempty"` } -type AssistantUsageDataQuotaSnapshotsValue struct { +type AssistantUsageQuotaSnapshot struct { // Whether the user has an unlimited usage entitlement IsUnlimitedEntitlement bool `json:"isUnlimitedEntitlement"` // Total requests allowed by the entitlement @@ -1824,7 +1828,7 @@ type AssistantUsageDataQuotaSnapshotsValue struct { } // Token usage detail for a single billing category -type AssistantUsageDataCopilotUsageTokenDetailsItem struct { +type AssistantUsageCopilotUsageTokenDetail struct { // Number of tokens in this billing batch BatchSize float64 `json:"batchSize"` // Cost per batch of tokens @@ -1836,15 +1840,15 @@ type AssistantUsageDataCopilotUsageTokenDetailsItem struct { } // Per-request cost and usage data from the CAPI copilot_usage response field -type AssistantUsageDataCopilotUsage struct { +type AssistantUsageCopilotUsage struct { // Itemized token usage breakdown - TokenDetails []AssistantUsageDataCopilotUsageTokenDetailsItem `json:"tokenDetails"` + TokenDetails []AssistantUsageCopilotUsageTokenDetail `json:"tokenDetails"` // Total cost in nano-AIU (AI Units) for this request TotalNanoAiu float64 `json:"totalNanoAiu"` } // Icon image for a resource -type ToolExecutionCompleteDataResultContentsItemIconsItem struct { +type ToolExecutionCompleteContentResourceLinkIcon struct { // URL or path to the icon image Src string `json:"src"` // MIME type of the icon image @@ -1852,13 +1856,13 @@ type ToolExecutionCompleteDataResultContentsItemIconsItem struct { // Available icon sizes (e.g., ['16x16', '32x32']) Sizes []string `json:"sizes,omitempty"` // Theme variant this icon is intended for - Theme *ToolExecutionCompleteDataResultContentsItemIconsItemTheme `json:"theme,omitempty"` + Theme *ToolExecutionCompleteContentResourceLinkIconTheme `json:"theme,omitempty"` } // A content block within a tool result, which may be text, terminal output, image, audio, or a resource -type ToolExecutionCompleteDataResultContentsItem struct { +type ToolExecutionCompleteContent struct { // Type discriminator - Type ToolExecutionCompleteDataResultContentsItemType `json:"type"` + Type ToolExecutionCompleteContentType `json:"type"` // The text content Text *string `json:"text,omitempty"` // Process exit code, if the command has completed @@ -1870,7 +1874,7 @@ type ToolExecutionCompleteDataResultContentsItem struct { // MIME type of the image (e.g., image/png, image/jpeg) MIMEType *string `json:"mimeType,omitempty"` // Icons associated with this resource - Icons []ToolExecutionCompleteDataResultContentsItemIconsItem `json:"icons,omitempty"` + Icons []ToolExecutionCompleteContentResourceLinkIcon `json:"icons,omitempty"` // Resource name identifier Name *string `json:"name,omitempty"` // Human-readable display title for the resource @@ -1886,17 +1890,17 @@ type ToolExecutionCompleteDataResultContentsItem struct { } // Tool execution result on success -type ToolExecutionCompleteDataResult struct { +type ToolExecutionCompleteResult struct { // Concise tool result text sent to the LLM for chat completion, potentially truncated for token efficiency Content string `json:"content"` // Full detailed tool result for UI/timeline display, preserving complete content such as diffs. Falls back to content when absent. DetailedContent *string `json:"detailedContent,omitempty"` // Structured content blocks (text, images, audio, resources) returned by the tool in their native format - Contents []ToolExecutionCompleteDataResultContentsItem `json:"contents,omitempty"` + Contents []ToolExecutionCompleteContent `json:"contents,omitempty"` } // Error details when the tool execution failed -type ToolExecutionCompleteDataError struct { +type ToolExecutionCompleteError struct { // Human-readable error message Message string `json:"message"` // Machine-readable error code @@ -1904,7 +1908,7 @@ type ToolExecutionCompleteDataError struct { } // Error details when the hook failed -type HookEndDataError struct { +type HookEndError struct { // Human-readable error message Message string `json:"message"` // Error stack trace, when available @@ -1912,7 +1916,7 @@ type HookEndDataError struct { } // Metadata about the prompt template and its construction -type SystemMessageDataMetadata struct { +type SystemMessageMetadata struct { // Version identifier of the prompt template used PromptVersion *string `json:"promptVersion,omitempty"` // Template variables used when constructing the prompt @@ -1920,15 +1924,15 @@ type SystemMessageDataMetadata struct { } // Structured metadata identifying what triggered this notification -type SystemNotificationDataKind struct { +type SystemNotification struct { // Type discriminator - Type SystemNotificationDataKindType `json:"type"` + Type SystemNotificationType `json:"type"` // Unique identifier of the background agent AgentID *string `json:"agentId,omitempty"` // Type of the agent (e.g., explore, task, general-purpose) AgentType *string `json:"agentType,omitempty"` // Whether the agent completed successfully or failed - Status *SystemNotificationDataKindStatus `json:"status,omitempty"` + Status *SystemNotificationAgentCompletedStatus `json:"status,omitempty"` // Human-readable description of the agent task Description *string `json:"description,omitempty"` // The full prompt given to the background agent @@ -1939,22 +1943,22 @@ type SystemNotificationDataKind struct { ExitCode *float64 `json:"exitCode,omitempty"` } -type PermissionRequestedDataPermissionRequestCommandsItem struct { +type PermissionRequestShellCommand struct { // Command identifier (e.g., executable name) Identifier string `json:"identifier"` // Whether this command is read-only (no side effects) ReadOnly bool `json:"readOnly"` } -type PermissionRequestedDataPermissionRequestPossibleUrlsItem struct { +type PermissionRequestShellPossibleUrl struct { // URL that may be accessed by the command URL string `json:"url"` } // Details of the permission being requested -type PermissionRequestedDataPermissionRequest struct { +type PermissionRequest struct { // Kind discriminator - Kind PermissionRequestedDataPermissionRequestKind `json:"kind"` + Kind PermissionRequestKind `json:"kind"` // Tool call ID that triggered this permission request ToolCallID *string `json:"toolCallId,omitempty"` // The complete shell command text to be executed @@ -1962,11 +1966,11 @@ type PermissionRequestedDataPermissionRequest struct { // Human-readable description of what the command intends to do Intention *string `json:"intention,omitempty"` // Parsed command identifiers found in the command text - Commands []PermissionRequestedDataPermissionRequestCommandsItem `json:"commands,omitempty"` + Commands []PermissionRequestShellCommand `json:"commands,omitempty"` // File paths that may be read or written by the command PossiblePaths []string `json:"possiblePaths,omitempty"` // URLs that may be accessed by the command - PossibleUrls []PermissionRequestedDataPermissionRequestPossibleUrlsItem `json:"possibleUrls,omitempty"` + PossibleUrls []PermissionRequestShellPossibleUrl `json:"possibleUrls,omitempty"` // Whether the command includes a file write redirection (e.g., > or >>) HasWriteFileRedirection *bool `json:"hasWriteFileRedirection,omitempty"` // Whether the UI can offer session-wide approval for this command pattern @@ -1994,7 +1998,7 @@ type PermissionRequestedDataPermissionRequest struct { // URL to be fetched URL *string `json:"url,omitempty"` // Whether this is a store or vote memory operation - Action *PermissionRequestedDataPermissionRequestAction `json:"action,omitempty"` + Action *PermissionRequestMemoryAction `json:"action,omitempty"` // Topic or subject of the memory (store only) Subject *string `json:"subject,omitempty"` // The fact being stored or voted on @@ -2002,7 +2006,7 @@ type PermissionRequestedDataPermissionRequest struct { // Source references for the stored fact (store only) Citations *string `json:"citations,omitempty"` // Vote direction (vote only) - Direction *PermissionRequestedDataPermissionRequestDirection `json:"direction,omitempty"` + Direction *PermissionRequestMemoryDirection `json:"direction,omitempty"` // Reason for the vote (vote only) Reason *string `json:"reason,omitempty"` // Description of what the custom tool does @@ -2014,13 +2018,13 @@ type PermissionRequestedDataPermissionRequest struct { } // The result of the permission request -type PermissionCompletedDataResult struct { +type PermissionCompletedResult struct { // The outcome of the permission request - Kind PermissionCompletedDataResultKind `json:"kind"` + Kind PermissionCompletedKind `json:"kind"` } // JSON Schema describing the form fields to present to the user (form mode only) -type ElicitationRequestedDataRequestedSchema struct { +type ElicitationRequestedSchema struct { // Schema type indicator (always 'object') Type string `json:"type"` // Form field definitions, keyed by field name @@ -2030,25 +2034,25 @@ type ElicitationRequestedDataRequestedSchema struct { } // Static OAuth client configuration, if the server specifies one -type McpOauthRequiredDataStaticClientConfig struct { +type McpOauthRequiredStaticClientConfig struct { // OAuth client ID for the server ClientID string `json:"clientId"` // Whether this is a public OAuth client PublicClient *bool `json:"publicClient,omitempty"` } -type CommandsChangedDataCommandsItem struct { +type CommandsChangedCommand struct { Name string `json:"name"` Description *string `json:"description,omitempty"` } // UI capability changes -type CapabilitiesChangedDataUI struct { +type CapabilitiesChangedUi struct { // Whether elicitation is now supported Elicitation *bool `json:"elicitation,omitempty"` } -type SessionSkillsLoadedDataSkillsItem struct { +type SkillsLoadedSkill struct { // Unique identifier for the skill Name string `json:"name"` // Description of what the skill does @@ -2063,7 +2067,7 @@ type SessionSkillsLoadedDataSkillsItem struct { Path *string `json:"path,omitempty"` } -type SessionCustomAgentsUpdatedDataAgentsItem struct { +type CustomAgentsUpdatedAgent struct { // Unique identifier for the agent ID string `json:"id"` // Internal name of the agent @@ -2082,265 +2086,255 @@ type SessionCustomAgentsUpdatedDataAgentsItem struct { Model *string `json:"model,omitempty"` } -type SessionMcpServersLoadedDataServersItem struct { +type McpServersLoadedServer struct { // Server name (config key) Name string `json:"name"` // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured - Status SessionMcpServersLoadedDataServersItemStatus `json:"status"` + Status McpServersLoadedServerStatus `json:"status"` // Configuration source: user, workspace, plugin, or builtin Source *string `json:"source,omitempty"` // Error message if the server failed to connect Error *string `json:"error,omitempty"` } -type SessionExtensionsLoadedDataExtensionsItem struct { +type ExtensionsLoadedExtension struct { // Source-qualified extension ID (e.g., 'project:my-ext', 'user:auth-helper') ID string `json:"id"` // Extension name (directory name) Name string `json:"name"` // Discovery source - Source SessionExtensionsLoadedDataExtensionsItemSource `json:"source"` + Source ExtensionsLoadedExtensionSource `json:"source"` // Current status: running, disabled, failed, or starting - Status SessionExtensionsLoadedDataExtensionsItemStatus `json:"status"` + Status ExtensionsLoadedExtensionStatus `json:"status"` } // Hosting platform type of the repository (github or ado) -type SessionStartDataContextHostType string +type StartContextHostType string const ( - SessionStartDataContextHostTypeGithub SessionStartDataContextHostType = "github" - SessionStartDataContextHostTypeAdo SessionStartDataContextHostType = "ado" + StartContextHostTypeGithub StartContextHostType = "github" + StartContextHostTypeAdo StartContextHostType = "ado" ) // The type of operation performed on the plan file -type SessionPlanChangedDataOperation string +type PlanChangedOperation string const ( - SessionPlanChangedDataOperationCreate SessionPlanChangedDataOperation = "create" - SessionPlanChangedDataOperationUpdate SessionPlanChangedDataOperation = "update" - SessionPlanChangedDataOperationDelete SessionPlanChangedDataOperation = "delete" + PlanChangedOperationCreate PlanChangedOperation = "create" + PlanChangedOperationUpdate PlanChangedOperation = "update" + PlanChangedOperationDelete PlanChangedOperation = "delete" ) // Whether the file was newly created or updated -type SessionWorkspaceFileChangedDataOperation string +type WorkspaceFileChangedOperation string const ( - SessionWorkspaceFileChangedDataOperationCreate SessionWorkspaceFileChangedDataOperation = "create" - SessionWorkspaceFileChangedDataOperationUpdate SessionWorkspaceFileChangedDataOperation = "update" + WorkspaceFileChangedOperationCreate WorkspaceFileChangedOperation = "create" + WorkspaceFileChangedOperationUpdate WorkspaceFileChangedOperation = "update" ) // Origin type of the session being handed off -type SessionHandoffDataSourceType string +type HandoffSourceType string const ( - SessionHandoffDataSourceTypeRemote SessionHandoffDataSourceType = "remote" - SessionHandoffDataSourceTypeLocal SessionHandoffDataSourceType = "local" + HandoffSourceTypeRemote HandoffSourceType = "remote" + HandoffSourceTypeLocal HandoffSourceType = "local" ) // Whether the session ended normally ("routine") or due to a crash/fatal error ("error") -type SessionShutdownDataShutdownType string +type ShutdownType string const ( - SessionShutdownDataShutdownTypeRoutine SessionShutdownDataShutdownType = "routine" - SessionShutdownDataShutdownTypeError SessionShutdownDataShutdownType = "error" + ShutdownTypeRoutine ShutdownType = "routine" + ShutdownTypeError ShutdownType = "error" ) -// Type discriminator for UserMessageDataAttachmentsItem. -type UserMessageDataAttachmentsItemType string +// Type discriminator for UserMessageAttachment. +type UserMessageAttachmentType string const ( - UserMessageDataAttachmentsItemTypeFile UserMessageDataAttachmentsItemType = "file" - UserMessageDataAttachmentsItemTypeDirectory UserMessageDataAttachmentsItemType = "directory" - UserMessageDataAttachmentsItemTypeSelection UserMessageDataAttachmentsItemType = "selection" - UserMessageDataAttachmentsItemTypeGithubReference UserMessageDataAttachmentsItemType = "github_reference" - UserMessageDataAttachmentsItemTypeBlob UserMessageDataAttachmentsItemType = "blob" + UserMessageAttachmentTypeFile UserMessageAttachmentType = "file" + UserMessageAttachmentTypeDirectory UserMessageAttachmentType = "directory" + UserMessageAttachmentTypeSelection UserMessageAttachmentType = "selection" + UserMessageAttachmentTypeGithubReference UserMessageAttachmentType = "github_reference" + UserMessageAttachmentTypeBlob UserMessageAttachmentType = "blob" ) // Type of GitHub reference -type UserMessageDataAttachmentsItemReferenceType string +type UserMessageAttachmentGithubReferenceType string const ( - UserMessageDataAttachmentsItemReferenceTypeIssue UserMessageDataAttachmentsItemReferenceType = "issue" - UserMessageDataAttachmentsItemReferenceTypePr UserMessageDataAttachmentsItemReferenceType = "pr" - UserMessageDataAttachmentsItemReferenceTypeDiscussion UserMessageDataAttachmentsItemReferenceType = "discussion" + UserMessageAttachmentGithubReferenceTypeIssue UserMessageAttachmentGithubReferenceType = "issue" + UserMessageAttachmentGithubReferenceTypePr UserMessageAttachmentGithubReferenceType = "pr" + UserMessageAttachmentGithubReferenceTypeDiscussion UserMessageAttachmentGithubReferenceType = "discussion" ) // The agent mode that was active when this message was sent -type UserMessageDataAgentMode string +type UserMessageAgentMode string const ( - UserMessageDataAgentModeInteractive UserMessageDataAgentMode = "interactive" - UserMessageDataAgentModePlan UserMessageDataAgentMode = "plan" - UserMessageDataAgentModeAutopilot UserMessageDataAgentMode = "autopilot" - UserMessageDataAgentModeShell UserMessageDataAgentMode = "shell" + UserMessageAgentModeInteractive UserMessageAgentMode = "interactive" + UserMessageAgentModePlan UserMessageAgentMode = "plan" + UserMessageAgentModeAutopilot UserMessageAgentMode = "autopilot" + UserMessageAgentModeShell UserMessageAgentMode = "shell" ) // Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. -type AssistantMessageDataToolRequestsItemType string +type AssistantMessageToolRequestType string const ( - AssistantMessageDataToolRequestsItemTypeFunction AssistantMessageDataToolRequestsItemType = "function" - AssistantMessageDataToolRequestsItemTypeCustom AssistantMessageDataToolRequestsItemType = "custom" + AssistantMessageToolRequestTypeFunction AssistantMessageToolRequestType = "function" + AssistantMessageToolRequestTypeCustom AssistantMessageToolRequestType = "custom" ) -// Type discriminator for ToolExecutionCompleteDataResultContentsItem. -type ToolExecutionCompleteDataResultContentsItemType string +// Type discriminator for ToolExecutionCompleteContent. +type ToolExecutionCompleteContentType string const ( - ToolExecutionCompleteDataResultContentsItemTypeText ToolExecutionCompleteDataResultContentsItemType = "text" - ToolExecutionCompleteDataResultContentsItemTypeTerminal ToolExecutionCompleteDataResultContentsItemType = "terminal" - ToolExecutionCompleteDataResultContentsItemTypeImage ToolExecutionCompleteDataResultContentsItemType = "image" - ToolExecutionCompleteDataResultContentsItemTypeAudio ToolExecutionCompleteDataResultContentsItemType = "audio" - ToolExecutionCompleteDataResultContentsItemTypeResourceLink ToolExecutionCompleteDataResultContentsItemType = "resource_link" - ToolExecutionCompleteDataResultContentsItemTypeResource ToolExecutionCompleteDataResultContentsItemType = "resource" + ToolExecutionCompleteContentTypeText ToolExecutionCompleteContentType = "text" + ToolExecutionCompleteContentTypeTerminal ToolExecutionCompleteContentType = "terminal" + ToolExecutionCompleteContentTypeImage ToolExecutionCompleteContentType = "image" + ToolExecutionCompleteContentTypeAudio ToolExecutionCompleteContentType = "audio" + ToolExecutionCompleteContentTypeResourceLink ToolExecutionCompleteContentType = "resource_link" + ToolExecutionCompleteContentTypeResource ToolExecutionCompleteContentType = "resource" ) // Theme variant this icon is intended for -type ToolExecutionCompleteDataResultContentsItemIconsItemTheme string +type ToolExecutionCompleteContentResourceLinkIconTheme string const ( - ToolExecutionCompleteDataResultContentsItemIconsItemThemeLight ToolExecutionCompleteDataResultContentsItemIconsItemTheme = "light" - ToolExecutionCompleteDataResultContentsItemIconsItemThemeDark ToolExecutionCompleteDataResultContentsItemIconsItemTheme = "dark" + ToolExecutionCompleteContentResourceLinkIconThemeLight ToolExecutionCompleteContentResourceLinkIconTheme = "light" + ToolExecutionCompleteContentResourceLinkIconThemeDark ToolExecutionCompleteContentResourceLinkIconTheme = "dark" ) // Message role: "system" for system prompts, "developer" for developer-injected instructions -type SystemMessageDataRole string +type SystemMessageRole string const ( - SystemMessageDataRoleSystem SystemMessageDataRole = "system" - SystemMessageDataRoleDeveloper SystemMessageDataRole = "developer" + SystemMessageRoleSystem SystemMessageRole = "system" + SystemMessageRoleDeveloper SystemMessageRole = "developer" ) -// Type discriminator for SystemNotificationDataKind. -type SystemNotificationDataKindType string +// Type discriminator for SystemNotification. +type SystemNotificationType string const ( - SystemNotificationDataKindTypeAgentCompleted SystemNotificationDataKindType = "agent_completed" - SystemNotificationDataKindTypeAgentIdle SystemNotificationDataKindType = "agent_idle" - SystemNotificationDataKindTypeShellCompleted SystemNotificationDataKindType = "shell_completed" - SystemNotificationDataKindTypeShellDetachedCompleted SystemNotificationDataKindType = "shell_detached_completed" + SystemNotificationTypeAgentCompleted SystemNotificationType = "agent_completed" + SystemNotificationTypeAgentIdle SystemNotificationType = "agent_idle" + SystemNotificationTypeShellCompleted SystemNotificationType = "shell_completed" + SystemNotificationTypeShellDetachedCompleted SystemNotificationType = "shell_detached_completed" ) // Whether the agent completed successfully or failed -type SystemNotificationDataKindStatus string +type SystemNotificationAgentCompletedStatus string const ( - SystemNotificationDataKindStatusCompleted SystemNotificationDataKindStatus = "completed" - SystemNotificationDataKindStatusFailed SystemNotificationDataKindStatus = "failed" + SystemNotificationAgentCompletedStatusCompleted SystemNotificationAgentCompletedStatus = "completed" + SystemNotificationAgentCompletedStatusFailed SystemNotificationAgentCompletedStatus = "failed" ) -// Kind discriminator for PermissionRequestedDataPermissionRequest. -type PermissionRequestedDataPermissionRequestKind string +// Kind discriminator for PermissionRequest. +type PermissionRequestKind string const ( - PermissionRequestedDataPermissionRequestKindShell PermissionRequestedDataPermissionRequestKind = "shell" - PermissionRequestedDataPermissionRequestKindWrite PermissionRequestedDataPermissionRequestKind = "write" - PermissionRequestedDataPermissionRequestKindRead PermissionRequestedDataPermissionRequestKind = "read" - PermissionRequestedDataPermissionRequestKindMcp PermissionRequestedDataPermissionRequestKind = "mcp" - PermissionRequestedDataPermissionRequestKindURL PermissionRequestedDataPermissionRequestKind = "url" - PermissionRequestedDataPermissionRequestKindMemory PermissionRequestedDataPermissionRequestKind = "memory" - PermissionRequestedDataPermissionRequestKindCustomTool PermissionRequestedDataPermissionRequestKind = "custom-tool" - PermissionRequestedDataPermissionRequestKindHook PermissionRequestedDataPermissionRequestKind = "hook" + PermissionRequestKindShell PermissionRequestKind = "shell" + PermissionRequestKindWrite PermissionRequestKind = "write" + PermissionRequestKindRead PermissionRequestKind = "read" + PermissionRequestKindMcp PermissionRequestKind = "mcp" + PermissionRequestKindURL PermissionRequestKind = "url" + PermissionRequestKindMemory PermissionRequestKind = "memory" + PermissionRequestKindCustomTool PermissionRequestKind = "custom-tool" + PermissionRequestKindHook PermissionRequestKind = "hook" ) // Whether this is a store or vote memory operation -type PermissionRequestedDataPermissionRequestAction string +type PermissionRequestMemoryAction string const ( - PermissionRequestedDataPermissionRequestActionStore PermissionRequestedDataPermissionRequestAction = "store" - PermissionRequestedDataPermissionRequestActionVote PermissionRequestedDataPermissionRequestAction = "vote" + PermissionRequestMemoryActionStore PermissionRequestMemoryAction = "store" + PermissionRequestMemoryActionVote PermissionRequestMemoryAction = "vote" ) // Vote direction (vote only) -type PermissionRequestedDataPermissionRequestDirection string +type PermissionRequestMemoryDirection string const ( - PermissionRequestedDataPermissionRequestDirectionUpvote PermissionRequestedDataPermissionRequestDirection = "upvote" - PermissionRequestedDataPermissionRequestDirectionDownvote PermissionRequestedDataPermissionRequestDirection = "downvote" + PermissionRequestMemoryDirectionUpvote PermissionRequestMemoryDirection = "upvote" + PermissionRequestMemoryDirectionDownvote PermissionRequestMemoryDirection = "downvote" ) // The outcome of the permission request -type PermissionCompletedDataResultKind string +type PermissionCompletedKind string const ( - PermissionCompletedDataResultKindApproved PermissionCompletedDataResultKind = "approved" - PermissionCompletedDataResultKindDeniedByRules PermissionCompletedDataResultKind = "denied-by-rules" - PermissionCompletedDataResultKindDeniedNoApprovalRuleAndCouldNotRequestFromUser PermissionCompletedDataResultKind = "denied-no-approval-rule-and-could-not-request-from-user" - PermissionCompletedDataResultKindDeniedInteractivelyByUser PermissionCompletedDataResultKind = "denied-interactively-by-user" - PermissionCompletedDataResultKindDeniedByContentExclusionPolicy PermissionCompletedDataResultKind = "denied-by-content-exclusion-policy" - PermissionCompletedDataResultKindDeniedByPermissionRequestHook PermissionCompletedDataResultKind = "denied-by-permission-request-hook" + PermissionCompletedKindApproved PermissionCompletedKind = "approved" + PermissionCompletedKindDeniedByRules PermissionCompletedKind = "denied-by-rules" + PermissionCompletedKindDeniedNoApprovalRuleAndCouldNotRequestFromUser PermissionCompletedKind = "denied-no-approval-rule-and-could-not-request-from-user" + PermissionCompletedKindDeniedInteractivelyByUser PermissionCompletedKind = "denied-interactively-by-user" + PermissionCompletedKindDeniedByContentExclusionPolicy PermissionCompletedKind = "denied-by-content-exclusion-policy" + PermissionCompletedKindDeniedByPermissionRequestHook PermissionCompletedKind = "denied-by-permission-request-hook" ) // Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. -type ElicitationRequestedDataMode string +type ElicitationRequestedMode string const ( - ElicitationRequestedDataModeForm ElicitationRequestedDataMode = "form" - ElicitationRequestedDataModeURL ElicitationRequestedDataMode = "url" + ElicitationRequestedModeForm ElicitationRequestedMode = "form" + ElicitationRequestedModeURL ElicitationRequestedMode = "url" ) // The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) -type ElicitationCompletedDataAction string +type ElicitationCompletedAction string const ( - ElicitationCompletedDataActionAccept ElicitationCompletedDataAction = "accept" - ElicitationCompletedDataActionDecline ElicitationCompletedDataAction = "decline" - ElicitationCompletedDataActionCancel ElicitationCompletedDataAction = "cancel" + ElicitationCompletedActionAccept ElicitationCompletedAction = "accept" + ElicitationCompletedActionDecline ElicitationCompletedAction = "decline" + ElicitationCompletedActionCancel ElicitationCompletedAction = "cancel" ) // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured -type SessionMcpServersLoadedDataServersItemStatus string +type McpServersLoadedServerStatus string const ( - SessionMcpServersLoadedDataServersItemStatusConnected SessionMcpServersLoadedDataServersItemStatus = "connected" - SessionMcpServersLoadedDataServersItemStatusFailed SessionMcpServersLoadedDataServersItemStatus = "failed" - SessionMcpServersLoadedDataServersItemStatusNeedsAuth SessionMcpServersLoadedDataServersItemStatus = "needs-auth" - SessionMcpServersLoadedDataServersItemStatusPending SessionMcpServersLoadedDataServersItemStatus = "pending" - SessionMcpServersLoadedDataServersItemStatusDisabled SessionMcpServersLoadedDataServersItemStatus = "disabled" - SessionMcpServersLoadedDataServersItemStatusNotConfigured SessionMcpServersLoadedDataServersItemStatus = "not_configured" + McpServersLoadedServerStatusConnected McpServersLoadedServerStatus = "connected" + McpServersLoadedServerStatusFailed McpServersLoadedServerStatus = "failed" + McpServersLoadedServerStatusNeedsAuth McpServersLoadedServerStatus = "needs-auth" + McpServersLoadedServerStatusPending McpServersLoadedServerStatus = "pending" + McpServersLoadedServerStatusDisabled McpServersLoadedServerStatus = "disabled" + McpServersLoadedServerStatusNotConfigured McpServersLoadedServerStatus = "not_configured" ) // Discovery source -type SessionExtensionsLoadedDataExtensionsItemSource string +type ExtensionsLoadedExtensionSource string const ( - SessionExtensionsLoadedDataExtensionsItemSourceProject SessionExtensionsLoadedDataExtensionsItemSource = "project" - SessionExtensionsLoadedDataExtensionsItemSourceUser SessionExtensionsLoadedDataExtensionsItemSource = "user" + ExtensionsLoadedExtensionSourceProject ExtensionsLoadedExtensionSource = "project" + ExtensionsLoadedExtensionSourceUser ExtensionsLoadedExtensionSource = "user" ) // Current status: running, disabled, failed, or starting -type SessionExtensionsLoadedDataExtensionsItemStatus string +type ExtensionsLoadedExtensionStatus string const ( - SessionExtensionsLoadedDataExtensionsItemStatusRunning SessionExtensionsLoadedDataExtensionsItemStatus = "running" - SessionExtensionsLoadedDataExtensionsItemStatusDisabled SessionExtensionsLoadedDataExtensionsItemStatus = "disabled" - SessionExtensionsLoadedDataExtensionsItemStatusFailed SessionExtensionsLoadedDataExtensionsItemStatus = "failed" - SessionExtensionsLoadedDataExtensionsItemStatusStarting SessionExtensionsLoadedDataExtensionsItemStatus = "starting" + ExtensionsLoadedExtensionStatusRunning ExtensionsLoadedExtensionStatus = "running" + ExtensionsLoadedExtensionStatusDisabled ExtensionsLoadedExtensionStatus = "disabled" + ExtensionsLoadedExtensionStatusFailed ExtensionsLoadedExtensionStatus = "failed" + ExtensionsLoadedExtensionStatusStarting ExtensionsLoadedExtensionStatus = "starting" ) // Type aliases for convenience. type ( - PermissionRequest = PermissionRequestedDataPermissionRequest - PermissionRequestKind = PermissionRequestedDataPermissionRequestKind - PermissionRequestCommand = PermissionRequestedDataPermissionRequestCommandsItem - PossibleURL = PermissionRequestedDataPermissionRequestPossibleUrlsItem - Attachment = UserMessageDataAttachmentsItem - AttachmentType = UserMessageDataAttachmentsItemType + PermissionRequestCommand = PermissionRequestShellCommand + PossibleURL = PermissionRequestShellPossibleUrl + Attachment = UserMessageAttachment + AttachmentType = UserMessageAttachmentType ) // Constant aliases for convenience. const ( - AttachmentTypeFile = UserMessageDataAttachmentsItemTypeFile - AttachmentTypeDirectory = UserMessageDataAttachmentsItemTypeDirectory - AttachmentTypeSelection = UserMessageDataAttachmentsItemTypeSelection - AttachmentTypeGithubReference = UserMessageDataAttachmentsItemTypeGithubReference - AttachmentTypeBlob = UserMessageDataAttachmentsItemTypeBlob - PermissionRequestKindShell = PermissionRequestedDataPermissionRequestKindShell - PermissionRequestKindWrite = PermissionRequestedDataPermissionRequestKindWrite - PermissionRequestKindRead = PermissionRequestedDataPermissionRequestKindRead - PermissionRequestKindMcp = PermissionRequestedDataPermissionRequestKindMcp - PermissionRequestKindURL = PermissionRequestedDataPermissionRequestKindURL - PermissionRequestKindMemory = PermissionRequestedDataPermissionRequestKindMemory - PermissionRequestKindCustomTool = PermissionRequestedDataPermissionRequestKindCustomTool - PermissionRequestKindHook = PermissionRequestedDataPermissionRequestKindHook + AttachmentTypeFile = UserMessageAttachmentTypeFile + AttachmentTypeDirectory = UserMessageAttachmentTypeDirectory + AttachmentTypeSelection = UserMessageAttachmentTypeSelection + AttachmentTypeGithubReference = UserMessageAttachmentTypeGithubReference + AttachmentTypeBlob = UserMessageAttachmentTypeBlob ) diff --git a/go/internal/e2e/agent_and_compact_rpc_test.go b/go/internal/e2e/agent_and_compact_rpc_test.go index dca773b5b..d7dd4a3fa 100644 --- a/go/internal/e2e/agent_and_compact_rpc_test.go +++ b/go/internal/e2e/agent_and_compact_rpc_test.go @@ -136,7 +136,7 @@ func TestAgentSelectionRpc(t *testing.T) { } // Select the agent - selectResult, err := session.RPC.Agent.Select(t.Context(), &rpc.SessionAgentSelectParams{Name: "test-agent"}) + selectResult, err := session.RPC.Agent.Select(t.Context(), &rpc.AgentSelectRequest{Name: "test-agent"}) if err != nil { t.Fatalf("Failed to select agent: %v", err) } @@ -191,7 +191,7 @@ func TestAgentSelectionRpc(t *testing.T) { } // Select then deselect - _, err = session.RPC.Agent.Select(t.Context(), &rpc.SessionAgentSelectParams{Name: "test-agent"}) + _, err = session.RPC.Agent.Select(t.Context(), &rpc.AgentSelectRequest{Name: "test-agent"}) if err != nil { t.Fatalf("Failed to select agent: %v", err) } diff --git a/go/internal/e2e/rpc_test.go b/go/internal/e2e/rpc_test.go index e38649e86..d5c7569a8 100644 --- a/go/internal/e2e/rpc_test.go +++ b/go/internal/e2e/rpc_test.go @@ -26,7 +26,7 @@ func TestRpc(t *testing.T) { t.Fatalf("Failed to start client: %v", err) } - result, err := client.RPC.Ping(t.Context(), &rpc.PingParams{Message: copilot.String("typed rpc test")}) + result, err := client.RPC.Ping(t.Context(), &rpc.PingRequest{Message: copilot.String("typed rpc test")}) if err != nil { t.Fatalf("Failed to call RPC.Ping: %v", err) } @@ -170,7 +170,7 @@ func TestSessionRpc(t *testing.T) { // Switch to a different model with reasoning effort re := "high" - result, err := session.RPC.Model.SwitchTo(t.Context(), &rpc.SessionModelSwitchToParams{ + result, err := session.RPC.Model.SwitchTo(t.Context(), &rpc.ModelSwitchToRequest{ ModelID: "gpt-4.1", ReasoningEffort: &re, }) @@ -218,17 +218,17 @@ func TestSessionRpc(t *testing.T) { if err != nil { t.Fatalf("Failed to get mode: %v", err) } - if initial.Mode != rpc.ModeInteractive { - t.Errorf("Expected initial mode 'interactive', got %q", initial.Mode) + if *initial != rpc.SessionModeInteractive { + t.Errorf("Expected initial mode 'interactive', got %q", *initial) } // Switch to plan mode - planResult, err := session.RPC.Mode.Set(t.Context(), &rpc.SessionModeSetParams{Mode: rpc.ModePlan}) + planResult, err := session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModePlan}) if err != nil { t.Fatalf("Failed to set mode to plan: %v", err) } - if planResult.Mode != rpc.ModePlan { - t.Errorf("Expected mode 'plan', got %q", planResult.Mode) + if *planResult != rpc.SessionModePlan { + t.Errorf("Expected mode 'plan', got %q", *planResult) } // Verify mode persisted @@ -236,17 +236,17 @@ func TestSessionRpc(t *testing.T) { if err != nil { t.Fatalf("Failed to get mode after plan: %v", err) } - if afterPlan.Mode != rpc.ModePlan { - t.Errorf("Expected mode 'plan' after set, got %q", afterPlan.Mode) + if *afterPlan != rpc.SessionModePlan { + t.Errorf("Expected mode 'plan' after set, got %q", *afterPlan) } // Switch back to interactive - interactiveResult, err := session.RPC.Mode.Set(t.Context(), &rpc.SessionModeSetParams{Mode: rpc.ModeInteractive}) + interactiveResult, err := session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModeInteractive}) if err != nil { t.Fatalf("Failed to set mode to interactive: %v", err) } - if interactiveResult.Mode != rpc.ModeInteractive { - t.Errorf("Expected mode 'interactive', got %q", interactiveResult.Mode) + if *interactiveResult != rpc.SessionModeInteractive { + t.Errorf("Expected mode 'interactive', got %q", *interactiveResult) } }) @@ -270,7 +270,7 @@ func TestSessionRpc(t *testing.T) { // Create/update plan planContent := "# Test Plan\n\n- Step 1\n- Step 2" - _, err = session.RPC.Plan.Update(t.Context(), &rpc.SessionPlanUpdateParams{Content: planContent}) + _, err = session.RPC.Plan.Update(t.Context(), &rpc.PlanUpdateRequest{Content: planContent}) if err != nil { t.Fatalf("Failed to update plan: %v", err) } @@ -323,7 +323,7 @@ func TestSessionRpc(t *testing.T) { // Create a file fileContent := "Hello, workspace!" - _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.SessionWorkspaceCreateFileParams{ + _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.WorkspaceCreateFileRequest{ Path: "test.txt", Content: fileContent, }) @@ -341,7 +341,7 @@ func TestSessionRpc(t *testing.T) { } // Read file - readResult, err := session.RPC.Workspace.ReadFile(t.Context(), &rpc.SessionWorkspaceReadFileParams{ + readResult, err := session.RPC.Workspace.ReadFile(t.Context(), &rpc.WorkspaceReadFileRequest{ Path: "test.txt", }) if err != nil { @@ -352,7 +352,7 @@ func TestSessionRpc(t *testing.T) { } // Create nested file - _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.SessionWorkspaceCreateFileParams{ + _, err = session.RPC.Workspace.CreateFile(t.Context(), &rpc.WorkspaceCreateFileRequest{ Path: "subdir/nested.txt", Content: "Nested content", }) diff --git a/go/internal/e2e/session_fs_test.go b/go/internal/e2e/session_fs_test.go index 4d006a856..be52c49dc 100644 --- a/go/internal/e2e/session_fs_test.go +++ b/go/internal/e2e/session_fs_test.go @@ -250,7 +250,7 @@ func TestSessionFs(t *testing.T) { var sessionFsConfig = &copilot.SessionFsConfig{ InitialCwd: "/", SessionStatePath: "/session-state", - Conventions: rpc.ConventionsPosix, + Conventions: rpc.SessionFSSetProviderConventionsPosix, } type testSessionFsHandler struct { @@ -258,7 +258,7 @@ type testSessionFsHandler struct { sessionID string } -func (h *testSessionFsHandler) ReadFile(request *rpc.SessionFSReadFileParams) (*rpc.SessionFSReadFileResult, error) { +func (h *testSessionFsHandler) ReadFile(request *rpc.SessionFSReadFileRequest) (*rpc.SessionFSReadFileResult, error) { content, err := os.ReadFile(providerPath(h.root, h.sessionID, request.Path)) if err != nil { return nil, err @@ -266,7 +266,7 @@ func (h *testSessionFsHandler) ReadFile(request *rpc.SessionFSReadFileParams) (* return &rpc.SessionFSReadFileResult{Content: string(content)}, nil } -func (h *testSessionFsHandler) WriteFile(request *rpc.SessionFSWriteFileParams) error { +func (h *testSessionFsHandler) WriteFile(request *rpc.SessionFSWriteFileRequest) error { path := providerPath(h.root, h.sessionID, request.Path) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err @@ -278,7 +278,7 @@ func (h *testSessionFsHandler) WriteFile(request *rpc.SessionFSWriteFileParams) return os.WriteFile(path, []byte(request.Content), mode) } -func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileParams) error { +func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileRequest) error { path := providerPath(h.root, h.sessionID, request.Path) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return err @@ -296,7 +296,7 @@ func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileParams return err } -func (h *testSessionFsHandler) Exists(request *rpc.SessionFSExistsParams) (*rpc.SessionFSExistsResult, error) { +func (h *testSessionFsHandler) Exists(request *rpc.SessionFSExistsRequest) (*rpc.SessionFSExistsResult, error) { _, err := os.Stat(providerPath(h.root, h.sessionID, request.Path)) if err == nil { return &rpc.SessionFSExistsResult{Exists: true}, nil @@ -307,7 +307,7 @@ func (h *testSessionFsHandler) Exists(request *rpc.SessionFSExistsParams) (*rpc. return nil, err } -func (h *testSessionFsHandler) Stat(request *rpc.SessionFSStatParams) (*rpc.SessionFSStatResult, error) { +func (h *testSessionFsHandler) Stat(request *rpc.SessionFSStatRequest) (*rpc.SessionFSStatResult, error) { info, err := os.Stat(providerPath(h.root, h.sessionID, request.Path)) if err != nil { return nil, err @@ -322,7 +322,7 @@ func (h *testSessionFsHandler) Stat(request *rpc.SessionFSStatParams) (*rpc.Sess }, nil } -func (h *testSessionFsHandler) Mkdir(request *rpc.SessionFSMkdirParams) error { +func (h *testSessionFsHandler) Mkdir(request *rpc.SessionFSMkdirRequest) error { path := providerPath(h.root, h.sessionID, request.Path) mode := os.FileMode(0o777) if request.Mode != nil { @@ -334,7 +334,7 @@ func (h *testSessionFsHandler) Mkdir(request *rpc.SessionFSMkdirParams) error { return os.Mkdir(path, mode) } -func (h *testSessionFsHandler) Readdir(request *rpc.SessionFSReaddirParams) (*rpc.SessionFSReaddirResult, error) { +func (h *testSessionFsHandler) Readdir(request *rpc.SessionFSReaddirRequest) (*rpc.SessionFSReaddirResult, error) { entries, err := os.ReadDir(providerPath(h.root, h.sessionID, request.Path)) if err != nil { return nil, err @@ -346,18 +346,18 @@ func (h *testSessionFsHandler) Readdir(request *rpc.SessionFSReaddirParams) (*rp return &rpc.SessionFSReaddirResult{Entries: names}, nil } -func (h *testSessionFsHandler) ReaddirWithTypes(request *rpc.SessionFSReaddirWithTypesParams) (*rpc.SessionFSReaddirWithTypesResult, error) { +func (h *testSessionFsHandler) ReaddirWithTypes(request *rpc.SessionFSReaddirWithTypesRequest) (*rpc.SessionFSReaddirWithTypesResult, error) { entries, err := os.ReadDir(providerPath(h.root, h.sessionID, request.Path)) if err != nil { return nil, err } - result := make([]rpc.Entry, 0, len(entries)) + result := make([]rpc.SessionFSReaddirWithTypesEntry, 0, len(entries)) for _, entry := range entries { - entryType := rpc.EntryTypeFile + entryType := rpc.SessionFSReaddirWithTypesEntryTypeFile if entry.IsDir() { - entryType = rpc.EntryTypeDirectory + entryType = rpc.SessionFSReaddirWithTypesEntryTypeDirectory } - result = append(result, rpc.Entry{ + result = append(result, rpc.SessionFSReaddirWithTypesEntry{ Name: entry.Name(), Type: entryType, }) @@ -365,7 +365,7 @@ func (h *testSessionFsHandler) ReaddirWithTypes(request *rpc.SessionFSReaddirWit return &rpc.SessionFSReaddirWithTypesResult{Entries: result}, nil } -func (h *testSessionFsHandler) Rm(request *rpc.SessionFSRmParams) error { +func (h *testSessionFsHandler) Rm(request *rpc.SessionFSRmRequest) error { path := providerPath(h.root, h.sessionID, request.Path) if request.Recursive != nil && *request.Recursive { err := os.RemoveAll(path) @@ -381,7 +381,7 @@ func (h *testSessionFsHandler) Rm(request *rpc.SessionFSRmParams) error { return err } -func (h *testSessionFsHandler) Rename(request *rpc.SessionFSRenameParams) error { +func (h *testSessionFsHandler) Rename(request *rpc.SessionFSRenameRequest) error { dest := providerPath(h.root, h.sessionID, request.Dest) if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { return err diff --git a/go/internal/e2e/session_test.go b/go/internal/e2e/session_test.go index 813036545..1fed130d3 100644 --- a/go/internal/e2e/session_test.go +++ b/go/internal/e2e/session_test.go @@ -1157,7 +1157,7 @@ func TestSessionLog(t *testing.T) { }) t.Run("should log warning message", func(t *testing.T) { - if err := session.Log(t.Context(), "Warning message", &copilot.LogOptions{Level: rpc.LevelWarning}); err != nil { + if err := session.Log(t.Context(), "Warning message", &copilot.LogOptions{Level: rpc.SessionLogLevelWarning}); err != nil { t.Fatalf("Log failed: %v", err) } @@ -1172,7 +1172,7 @@ func TestSessionLog(t *testing.T) { }) t.Run("should log error message", func(t *testing.T) { - if err := session.Log(t.Context(), "Error message", &copilot.LogOptions{Level: rpc.LevelError}); err != nil { + if err := session.Log(t.Context(), "Error message", &copilot.LogOptions{Level: rpc.SessionLogLevelError}); err != nil { t.Fatalf("Log failed: %v", err) } diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 698b3e95e..90925defb 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -13,308 +13,299 @@ import ( type PingResult struct { // Echoed message (or default greeting) - Message string `json:"message"` + Message string `json:"message"` // Server protocol version number - ProtocolVersion float64 `json:"protocolVersion"` + ProtocolVersion int64 `json:"protocolVersion"` // Server timestamp in milliseconds - Timestamp float64 `json:"timestamp"` + Timestamp int64 `json:"timestamp"` } -type PingParams struct { +type PingRequest struct { // Optional message to echo back - Message *string `json:"message,omitempty"` + Message *string `json:"message,omitempty"` } -type ModelsListResult struct { +type ModelList struct { // List of available models with full metadata - Models []Model `json:"models"` + Models []Model `json:"models"` } type Model struct { - // Billing information - Billing *Billing `json:"billing,omitempty"` - // Model capabilities and limits - Capabilities ModelCapabilities `json:"capabilities"` + Billing *ModelBilling `json:"billing,omitempty"` + Capabilities ModelCapabilities `json:"capabilities"` // Default reasoning effort level (only present if model supports reasoning effort) - DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` + DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` // Model identifier (e.g., "claude-sonnet-4.5") - ID string `json:"id"` + ID string `json:"id"` // Display name - Name string `json:"name"` - // Policy state (if applicable) - Policy *Policy `json:"policy,omitempty"` + Name string `json:"name"` + Policy *ModelPolicy `json:"policy,omitempty"` // Supported reasoning effort levels (only present if model supports reasoning effort) - SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` + SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` } // Billing information -type Billing struct { +type ModelBilling struct { // Billing cost multiplier relative to the base rate - Multiplier float64 `json:"multiplier"` + Multiplier float64 `json:"multiplier"` } // Model capabilities and limits type ModelCapabilities struct { - // Token limits for prompts, outputs, and context window - Limits ModelCapabilitiesLimits `json:"limits"` - // Feature flags indicating what the model supports + Limits ModelCapabilitiesLimits `json:"limits"` Supports ModelCapabilitiesSupports `json:"supports"` } // Token limits for prompts, outputs, and context window type ModelCapabilitiesLimits struct { // Maximum total context window size in tokens - MaxContextWindowTokens float64 `json:"max_context_window_tokens"` + MaxContextWindowTokens int64 `json:"max_context_window_tokens"` // Maximum number of output/completion tokens - MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` + MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` // Maximum number of prompt/input tokens - MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` - // Vision-specific limits - Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"` + MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` + Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"` } // Vision-specific limits type ModelCapabilitiesLimitsVision struct { // Maximum image size in bytes - MaxPromptImageSize float64 `json:"max_prompt_image_size"` + MaxPromptImageSize int64 `json:"max_prompt_image_size"` // Maximum number of images per prompt - MaxPromptImages float64 `json:"max_prompt_images"` + MaxPromptImages int64 `json:"max_prompt_images"` // MIME types the model accepts - SupportedMediaTypes []string `json:"supported_media_types"` + SupportedMediaTypes []string `json:"supported_media_types"` } // Feature flags indicating what the model supports type ModelCapabilitiesSupports struct { // Whether this model supports reasoning effort configuration - ReasoningEffort *bool `json:"reasoningEffort,omitempty"` + ReasoningEffort *bool `json:"reasoningEffort,omitempty"` // Whether this model supports vision/image input - Vision *bool `json:"vision,omitempty"` + Vision *bool `json:"vision,omitempty"` } // Policy state (if applicable) -type Policy struct { +type ModelPolicy struct { // Current policy state for this model - State string `json:"state"` + State string `json:"state"` // Usage terms or conditions for this model - Terms string `json:"terms"` + Terms string `json:"terms"` } -type ToolsListResult struct { +type ToolList struct { // List of available built-in tools with metadata - Tools []Tool `json:"tools"` + Tools []Tool `json:"tools"` } type Tool struct { // Description of what the tool does - Description string `json:"description"` + Description string `json:"description"` // Optional instructions for how to use this tool effectively - Instructions *string `json:"instructions,omitempty"` + Instructions *string `json:"instructions,omitempty"` // Tool identifier (e.g., "bash", "grep", "str_replace_editor") - Name string `json:"name"` + Name string `json:"name"` // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP // tools) - NamespacedName *string `json:"namespacedName,omitempty"` + NamespacedName *string `json:"namespacedName,omitempty"` // JSON Schema for the tool's input parameters - Parameters map[string]any `json:"parameters,omitempty"` + Parameters map[string]any `json:"parameters,omitempty"` } -type ToolsListParams struct { +type ToolsListRequest struct { // Optional model ID — when provided, the returned tool list reflects model-specific // overrides - Model *string `json:"model,omitempty"` + Model *string `json:"model,omitempty"` } -type AccountGetQuotaResult struct { +type AccountQuota struct { // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) - QuotaSnapshots map[string]QuotaSnapshot `json:"quotaSnapshots"` + QuotaSnapshots map[string]AccountQuotaSnapshot `json:"quotaSnapshots"` } -type QuotaSnapshot struct { +import "time" + +type AccountQuotaSnapshot struct { // Number of requests included in the entitlement - EntitlementRequests float64 `json:"entitlementRequests"` + EntitlementRequests int64 `json:"entitlementRequests"` // Number of overage requests made this period - Overage float64 `json:"overage"` + Overage int64 `json:"overage"` // Whether pay-per-request usage is allowed when quota is exhausted - OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` + OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` // Percentage of entitlement remaining - RemainingPercentage float64 `json:"remainingPercentage"` + RemainingPercentage float64 `json:"remainingPercentage"` // Date when the quota resets (ISO 8601) - ResetDate *string `json:"resetDate,omitempty"` + ResetDate *time.Time `json:"resetDate,omitempty"` // Number of requests used so far this period - UsedRequests float64 `json:"usedRequests"` + UsedRequests int64 `json:"usedRequests"` } -type MCPConfigListResult struct { +type MCPConfigList struct { // All MCP servers from user config, keyed by name - Servers map[string]ServerValue `json:"servers"` + Servers map[string]MCPConfigServer `json:"servers"` } // MCP server configuration (local/stdio or remote/http) -type ServerValue struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *FilterMappingUnion `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` - Timeout *float64 `json:"timeout,omitempty"` +type MCPConfigServer struct { + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + // Timeout in milliseconds for tool calls to this server. + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } -type MCPConfigAddParams struct { - // MCP server configuration (local/stdio or remote/http) - Config MCPConfigAddParamsConfig `json:"config"` +type MCPConfigAddRequest struct { + Config MCPConfigAddConfig `json:"config"` // Unique name for the MCP server - Name string `json:"name"` + Name string `json:"name"` } // MCP server configuration (local/stdio or remote/http) -type MCPConfigAddParamsConfig struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *FilterMappingUnion `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` - Timeout *float64 `json:"timeout,omitempty"` +type MCPConfigAddConfig struct { + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + // Timeout in milliseconds for tool calls to this server. + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } -type MCPConfigUpdateParams struct { - // MCP server configuration (local/stdio or remote/http) - Config MCPConfigUpdateParamsConfig `json:"config"` +type MCPConfigUpdateRequest struct { + Config MCPConfigUpdateConfig `json:"config"` // Name of the MCP server to update - Name string `json:"name"` + Name string `json:"name"` } // MCP server configuration (local/stdio or remote/http) -type MCPConfigUpdateParamsConfig struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *FilterMappingUnion `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` - Timeout *float64 `json:"timeout,omitempty"` +type MCPConfigUpdateConfig struct { + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + // Timeout in milliseconds for tool calls to this server. + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } -type MCPConfigRemoveParams struct { +type MCPConfigRemoveRequest struct { // Name of the MCP server to remove - Name string `json:"name"` + Name string `json:"name"` } type MCPDiscoverResult struct { // MCP servers discovered from all sources - Servers []DiscoveredMCPServer `json:"servers"` + Servers []DiscoveredMCPServer `json:"servers"` } type DiscoveredMCPServer struct { // Whether the server is enabled (not in the disabled list) - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Server name (config key) - Name string `json:"name"` - // Configuration source - Source ServerSource `json:"source"` - // Server type: local, stdio, http, or sse - Type *string `json:"type,omitempty"` + Name string `json:"name"` + Source MCPServerSource `json:"source"` + Type *DiscoveredMCPServerType `json:"type,omitempty"` } -type MCPDiscoverParams struct { +type MCPDiscoverRequest struct { // Working directory used as context for discovery (e.g., plugin resolution) - WorkingDirectory *string `json:"workingDirectory,omitempty"` + WorkingDirectory *string `json:"workingDirectory,omitempty"` } type SessionFSSetProviderResult struct { // Whether the provider was set successfully - Success bool `json:"success"` + Success bool `json:"success"` } -type SessionFSSetProviderParams struct { - // Path conventions used by this filesystem - Conventions Conventions `json:"conventions"` +type SessionFSSetProviderRequest struct { + Conventions SessionFSSetProviderConventions `json:"conventions"` // Initial working directory for sessions - InitialCwd string `json:"initialCwd"` + InitialCwd string `json:"initialCwd"` // Path within each session's SessionFs where the runtime stores files for that session - SessionStatePath string `json:"sessionStatePath"` + SessionStatePath string `json:"sessionStatePath"` } // Experimental: SessionsForkResult is part of an experimental API and may change or be removed. type SessionsForkResult struct { // The new forked session's ID - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -// Experimental: SessionsForkParams is part of an experimental API and may change or be removed. -type SessionsForkParams struct { +// Experimental: SessionsForkRequest is part of an experimental API and may change or be removed. +type SessionsForkRequest struct { // Source session ID to fork from - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` // Optional event ID boundary. When provided, the fork includes only events before this ID // (exclusive). When omitted, all events are included. - ToEventID *string `json:"toEventId,omitempty"` + ToEventID *string `json:"toEventId,omitempty"` } -type SessionModelGetCurrentResult struct { +type ModelCurrent struct { // Currently active model identifier - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } -type SessionModelSwitchToResult struct { +type ModelSwitchToResult struct { // Currently active model identifier after the switch - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } -type SessionModelSwitchToParams struct { - // Override individual model capabilities resolved by the runtime - ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` +type ModelSwitchToRequest struct { + ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` // Model identifier to switch to - ModelID string `json:"modelId"` + ModelID string `json:"modelId"` // Reasoning effort level to use for the model - ReasoningEffort *string `json:"reasoningEffort,omitempty"` + ReasoningEffort *string `json:"reasoningEffort,omitempty"` } // Override individual model capabilities resolved by the runtime type ModelCapabilitiesOverride struct { - // Token limits for prompts, outputs, and context window - Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"` - // Feature flags indicating what the model supports + Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"` Supports *ModelCapabilitiesOverrideSupports `json:"supports,omitempty"` } // Token limits for prompts, outputs, and context window type ModelCapabilitiesOverrideLimits struct { // Maximum total context window size in tokens - MaxContextWindowTokens *float64 `json:"max_context_window_tokens,omitempty"` - MaxOutputTokens *float64 `json:"max_output_tokens,omitempty"` - MaxPromptTokens *float64 `json:"max_prompt_tokens,omitempty"` - Vision *ModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"` + MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"` + MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` + MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` + Vision *ModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"` } type ModelCapabilitiesOverrideLimitsVision struct { // Maximum image size in bytes - MaxPromptImageSize *float64 `json:"max_prompt_image_size,omitempty"` + MaxPromptImageSize *int64 `json:"max_prompt_image_size,omitempty"` // Maximum number of images per prompt - MaxPromptImages *float64 `json:"max_prompt_images,omitempty"` + MaxPromptImages *int64 `json:"max_prompt_images,omitempty"` // MIME types the model accepts - SupportedMediaTypes []string `json:"supported_media_types,omitempty"` + SupportedMediaTypes []string `json:"supported_media_types,omitempty"` } // Feature flags indicating what the model supports @@ -323,417 +314,389 @@ type ModelCapabilitiesOverrideSupports struct { Vision *bool `json:"vision,omitempty"` } -type SessionModeGetResult struct { - // The current agent mode. - Mode Mode `json:"mode"` +type ModeSetRequest struct { + Mode SessionMode `json:"mode"` } -type SessionModeSetResult struct { - // The agent mode after switching. - Mode Mode `json:"mode"` -} - -type SessionModeSetParams struct { - // The mode to switch to. Valid values: "interactive", "plan", "autopilot". - Mode Mode `json:"mode"` -} - -type SessionPlanReadResult struct { +type Plan struct { // The content of the plan file, or null if it does not exist - Content *string `json:"content"` + Content *string `json:"content"` // Whether the plan file exists in the workspace - Exists bool `json:"exists"` + Exists bool `json:"exists"` // Absolute file path of the plan file, or null if workspace is not enabled - Path *string `json:"path"` + Path *string `json:"path"` } -type SessionPlanUpdateResult struct { +type PlanUpdateResult struct { } -type SessionPlanUpdateParams struct { +type PlanUpdateRequest struct { // The new content for the plan file - Content string `json:"content"` + Content string `json:"content"` } -type SessionPlanDeleteResult struct { +type PlanDelete struct { } -type SessionWorkspaceListFilesResult struct { +type WorkspaceFiles struct { // Relative file paths in the workspace files directory - Files []string `json:"files"` + Files []string `json:"files"` } -type SessionWorkspaceReadFileResult struct { +type WorkspaceReadFileResult struct { // File content as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` } -type SessionWorkspaceReadFileParams struct { +type WorkspaceReadFileRequest struct { // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } -type SessionWorkspaceCreateFileResult struct { +type WorkspaceCreateFileResult struct { } -type SessionWorkspaceCreateFileParams struct { +type WorkspaceCreateFileRequest struct { // File content to write as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } -// Experimental: SessionFleetStartResult is part of an experimental API and may change or be removed. -type SessionFleetStartResult struct { +// Experimental: FleetStartResult is part of an experimental API and may change or be removed. +type FleetStartResult struct { // Whether fleet mode was successfully activated - Started bool `json:"started"` + Started bool `json:"started"` } -// Experimental: SessionFleetStartParams is part of an experimental API and may change or be removed. -type SessionFleetStartParams struct { +// Experimental: FleetStartRequest is part of an experimental API and may change or be removed. +type FleetStartRequest struct { // Optional user prompt to combine with fleet instructions - Prompt *string `json:"prompt,omitempty"` + Prompt *string `json:"prompt,omitempty"` } -// Experimental: SessionAgentListResult is part of an experimental API and may change or be removed. -type SessionAgentListResult struct { +// Experimental: AgentList is part of an experimental API and may change or be removed. +type AgentList struct { // Available custom agents - Agents []SessionAgentListResultAgent `json:"agents"` + Agents []Agent `json:"agents"` } -type SessionAgentListResultAgent struct { +type Agent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionAgentGetCurrentResult is part of an experimental API and may change or be removed. -type SessionAgentGetCurrentResult struct { +// Experimental: AgentCurrent is part of an experimental API and may change or be removed. +type AgentCurrent struct { // Currently selected custom agent, or null if using the default agent - Agent *SessionAgentGetCurrentResultAgent `json:"agent"` + Agent *AgentCurrentAgent `json:"agent"` } -type SessionAgentGetCurrentResultAgent struct { +type AgentCurrentAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionAgentSelectResult is part of an experimental API and may change or be removed. -type SessionAgentSelectResult struct { - // The newly selected custom agent - Agent SessionAgentSelectResultAgent `json:"agent"` +// Experimental: AgentSelectResult is part of an experimental API and may change or be removed. +type AgentSelectResult struct { + Agent AgentSelectAgent `json:"agent"` } // The newly selected custom agent -type SessionAgentSelectResultAgent struct { +type AgentSelectAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionAgentSelectParams is part of an experimental API and may change or be removed. -type SessionAgentSelectParams struct { +// Experimental: AgentSelectRequest is part of an experimental API and may change or be removed. +type AgentSelectRequest struct { // Name of the custom agent to select - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionAgentDeselectResult is part of an experimental API and may change or be removed. -type SessionAgentDeselectResult struct { +// Experimental: AgentDeselect is part of an experimental API and may change or be removed. +type AgentDeselect struct { } -// Experimental: SessionAgentReloadResult is part of an experimental API and may change or be removed. -type SessionAgentReloadResult struct { +// Experimental: AgentReload is part of an experimental API and may change or be removed. +type AgentReload struct { // Reloaded custom agents - Agents []SessionAgentReloadResultAgent `json:"agents"` + Agents []AgentReloadAgent `json:"agents"` } -type SessionAgentReloadResultAgent struct { +type AgentReloadAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionSkillsListResult is part of an experimental API and may change or be removed. -type SessionSkillsListResult struct { +// Experimental: SkillList is part of an experimental API and may change or be removed. +type SkillList struct { // Available skills - Skills []Skill `json:"skills"` + Skills []Skill `json:"skills"` } type Skill struct { // Description of what the skill does - Description string `json:"description"` + Description string `json:"description"` // Whether the skill is currently enabled - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Unique identifier for the skill - Name string `json:"name"` + Name string `json:"name"` // Absolute path to the skill file - Path *string `json:"path,omitempty"` + Path *string `json:"path,omitempty"` // Source location type (e.g., project, personal, plugin) - Source string `json:"source"` + Source string `json:"source"` // Whether the skill can be invoked by the user as a slash command - UserInvocable bool `json:"userInvocable"` + UserInvocable bool `json:"userInvocable"` } -// Experimental: SessionSkillsEnableResult is part of an experimental API and may change or be removed. -type SessionSkillsEnableResult struct { +// Experimental: SkillsEnableResult is part of an experimental API and may change or be removed. +type SkillsEnableResult struct { } -// Experimental: SessionSkillsEnableParams is part of an experimental API and may change or be removed. -type SessionSkillsEnableParams struct { +// Experimental: SkillsEnableRequest is part of an experimental API and may change or be removed. +type SkillsEnableRequest struct { // Name of the skill to enable - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionSkillsDisableResult is part of an experimental API and may change or be removed. -type SessionSkillsDisableResult struct { +// Experimental: SkillsDisableResult is part of an experimental API and may change or be removed. +type SkillsDisableResult struct { } -// Experimental: SessionSkillsDisableParams is part of an experimental API and may change or be removed. -type SessionSkillsDisableParams struct { +// Experimental: SkillsDisableRequest is part of an experimental API and may change or be removed. +type SkillsDisableRequest struct { // Name of the skill to disable - Name string `json:"name"` + Name string `json:"name"` } -// Experimental: SessionSkillsReloadResult is part of an experimental API and may change or be removed. -type SessionSkillsReloadResult struct { +// Experimental: SkillsReload is part of an experimental API and may change or be removed. +type SkillsReload struct { } -type SessionMCPListResult struct { +type MCPList struct { // Configured MCP servers - Servers []ServerElement `json:"servers"` + Servers []MCPServer `json:"servers"` } -type ServerElement struct { +type MCPServer struct { // Error message if the server failed to connect - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Server name (config key) - Name string `json:"name"` - // Configuration source: user, workspace, plugin, or builtin - Source *string `json:"source,omitempty"` - // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured - Status ServerStatus `json:"status"` + Name string `json:"name"` + Source *MCPServerSource `json:"source,omitempty"` + Status MCPServerStatus `json:"status"` } -type SessionMCPEnableResult struct { +type MCPEnableResult struct { } -type SessionMCPEnableParams struct { +type MCPEnableRequest struct { // Name of the MCP server to enable - ServerName string `json:"serverName"` + ServerName string `json:"serverName"` } -type SessionMCPDisableResult struct { +type MCPDisableResult struct { } -type SessionMCPDisableParams struct { +type MCPDisableRequest struct { // Name of the MCP server to disable - ServerName string `json:"serverName"` + ServerName string `json:"serverName"` } -type SessionMCPReloadResult struct { +type MCPReload struct { } -// Experimental: SessionPluginsListResult is part of an experimental API and may change or be removed. -type SessionPluginsListResult struct { +// Experimental: PluginList is part of an experimental API and may change or be removed. +type PluginList struct { // Installed plugins - Plugins []PluginElement `json:"plugins"` + Plugins []PluginElement `json:"plugins"` } type PluginElement struct { // Whether the plugin is currently enabled - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Marketplace the plugin came from - Marketplace string `json:"marketplace"` + Marketplace string `json:"marketplace"` // Plugin name - Name string `json:"name"` + Name string `json:"name"` // Installed version - Version *string `json:"version,omitempty"` + Version *string `json:"version,omitempty"` } -// Experimental: SessionExtensionsListResult is part of an experimental API and may change or be removed. -type SessionExtensionsListResult struct { +// Experimental: ExtensionList is part of an experimental API and may change or be removed. +type ExtensionList struct { // Discovered extensions and their current status - Extensions []Extension `json:"extensions"` + Extensions []Extension `json:"extensions"` } type Extension struct { // Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper') - ID string `json:"id"` + ID string `json:"id"` // Extension name (directory name) - Name string `json:"name"` + Name string `json:"name"` // Process ID if the extension is running - PID *int64 `json:"pid,omitempty"` - // Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) - Source ExtensionSource `json:"source"` - // Current status: running, disabled, failed, or starting - Status ExtensionStatus `json:"status"` + PID *int64 `json:"pid,omitempty"` + Source ExtensionSource `json:"source"` + Status ExtensionStatus `json:"status"` } -// Experimental: SessionExtensionsEnableResult is part of an experimental API and may change or be removed. -type SessionExtensionsEnableResult struct { +// Experimental: ExtensionsEnableResult is part of an experimental API and may change or be removed. +type ExtensionsEnableResult struct { } -// Experimental: SessionExtensionsEnableParams is part of an experimental API and may change or be removed. -type SessionExtensionsEnableParams struct { +// Experimental: ExtensionsEnableRequest is part of an experimental API and may change or be removed. +type ExtensionsEnableRequest struct { // Source-qualified extension ID to enable - ID string `json:"id"` + ID string `json:"id"` } -// Experimental: SessionExtensionsDisableResult is part of an experimental API and may change or be removed. -type SessionExtensionsDisableResult struct { +// Experimental: ExtensionsDisableResult is part of an experimental API and may change or be removed. +type ExtensionsDisableResult struct { } -// Experimental: SessionExtensionsDisableParams is part of an experimental API and may change or be removed. -type SessionExtensionsDisableParams struct { +// Experimental: ExtensionsDisableRequest is part of an experimental API and may change or be removed. +type ExtensionsDisableRequest struct { // Source-qualified extension ID to disable - ID string `json:"id"` + ID string `json:"id"` } -// Experimental: SessionExtensionsReloadResult is part of an experimental API and may change or be removed. -type SessionExtensionsReloadResult struct { +// Experimental: ExtensionsReload is part of an experimental API and may change or be removed. +type ExtensionsReload struct { } -type SessionToolsHandlePendingToolCallResult struct { +type HandleToolCallResult struct { // Whether the tool call result was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } -type SessionToolsHandlePendingToolCallParams struct { +type ToolsHandlePendingToolCallRequest struct { // Error message if the tool call failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Request ID of the pending tool call - RequestID string `json:"requestId"` - // Tool call result (string or expanded result object) - Result *ResultUnion `json:"result"` + RequestID string `json:"requestId"` + Result *ToolsHandlePendingToolCall `json:"result"` } -type ResultResult struct { +type ToolCallResult struct { // Error message if the tool call failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Type of the tool result - ResultType *string `json:"resultType,omitempty"` + ResultType *string `json:"resultType,omitempty"` // Text result to send back to the LLM - TextResultForLlm string `json:"textResultForLlm"` + TextResultForLlm string `json:"textResultForLlm"` // Telemetry data from tool execution - ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` + ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` } -type SessionCommandsHandlePendingCommandResult struct { +type CommandsHandlePendingCommandResult struct { // Whether the command was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } -type SessionCommandsHandlePendingCommandParams struct { +type CommandsHandlePendingCommandRequest struct { // Error message if the command handler failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Request ID from the command invocation event - RequestID string `json:"requestId"` + RequestID string `json:"requestId"` } -type SessionUIElicitationResult struct { - // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - Action Action `json:"action"` - // The form values submitted by the user (present when action is 'accept') - Content map[string]*Content `json:"content,omitempty"` +// The elicitation response (accept with form values, decline, or cancel) +type UIElicitationResponse struct { + Action ElicitationResponseAction `json:"action"` + Content map[string]*ElicitationFieldValue `json:"content,omitempty"` } -type SessionUIElicitationParams struct { +type UIElicitationRequest struct { // Message describing what information is needed from the user - Message string `json:"message"` - // JSON Schema describing the form fields to present to the user - RequestedSchema RequestedSchema `json:"requestedSchema"` + Message string `json:"message"` + RequestedSchema UIElicitationSchema `json:"requestedSchema"` } // JSON Schema describing the form fields to present to the user -type RequestedSchema struct { +type UIElicitationSchema struct { // Form field definitions, keyed by field name - Properties map[string]Property `json:"properties"` + Properties map[string]UIElicitationSchemaProperty `json:"properties"` // List of required field names - Required []string `json:"required,omitempty"` + Required []string `json:"required,omitempty"` // Schema type indicator (always 'object') - Type RequestedSchemaType `json:"type"` -} - -type Property struct { - Default *Content `json:"default"` - Description *string `json:"description,omitempty"` - Enum []string `json:"enum,omitempty"` - EnumNames []string `json:"enumNames,omitempty"` - Title *string `json:"title,omitempty"` - Type PropertyType `json:"type"` - OneOf []OneOf `json:"oneOf,omitempty"` - Items *Items `json:"items,omitempty"` - MaxItems *float64 `json:"maxItems,omitempty"` - MinItems *float64 `json:"minItems,omitempty"` - Format *Format `json:"format,omitempty"` - MaxLength *float64 `json:"maxLength,omitempty"` - MinLength *float64 `json:"minLength,omitempty"` - Maximum *float64 `json:"maximum,omitempty"` - Minimum *float64 `json:"minimum,omitempty"` -} - -type Items struct { - Enum []string `json:"enum,omitempty"` - Type *ItemsType `json:"type,omitempty"` - AnyOf []AnyOf `json:"anyOf,omitempty"` -} - -type AnyOf struct { + Type RequestedSchemaType `json:"type"` +} + +type UIElicitationSchemaProperty struct { + Default *ElicitationFieldValue `json:"default"` + Description *string `json:"description,omitempty"` + Enum []string `json:"enum,omitempty"` + EnumNames []string `json:"enumNames,omitempty"` + Title *string `json:"title,omitempty"` + Type UIElicitationSchemaPropertyNumberType `json:"type"` + OneOf []ElicitationStringOneOfFieldOneOf `json:"oneOf,omitempty"` + Items *ElicitationArrayFieldItems `json:"items,omitempty"` + MaxItems *float64 `json:"maxItems,omitempty"` + MinItems *float64 `json:"minItems,omitempty"` + Format *UIElicitationSchemaPropertyStringFormat `json:"format,omitempty"` + MaxLength *float64 `json:"maxLength,omitempty"` + MinLength *float64 `json:"minLength,omitempty"` + Maximum *float64 `json:"maximum,omitempty"` + Minimum *float64 `json:"minimum,omitempty"` +} + +type ElicitationArrayFieldItems struct { + Enum []string `json:"enum,omitempty"` + Type *ItemsType `json:"type,omitempty"` + AnyOf []ElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"` +} + +type ElicitationArrayAnyOfFieldItemsAnyOf struct { Const string `json:"const"` Title string `json:"title"` } -type OneOf struct { +type ElicitationStringOneOfFieldOneOf struct { Const string `json:"const"` Title string `json:"title"` } -type SessionUIHandlePendingElicitationResult struct { +type UIElicitationResult struct { // Whether the response was accepted. False if the request was already resolved by another // client. - Success bool `json:"success"` + Success bool `json:"success"` } -type SessionUIHandlePendingElicitationParams struct { +type HandlePendingElicitationRequest struct { // The unique request ID from the elicitation.requested event - RequestID string `json:"requestId"` - // The elicitation response (accept with form values, decline, or cancel) - Result SessionUIHandlePendingElicitationParamsResult `json:"result"` -} - -// The elicitation response (accept with form values, decline, or cancel) -type SessionUIHandlePendingElicitationParamsResult struct { - // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - Action Action `json:"action"` - // The form values submitted by the user (present when action is 'accept') - Content map[string]*Content `json:"content,omitempty"` + RequestID string `json:"requestId"` + Result UIElicitationResponse `json:"result"` } -type SessionPermissionsHandlePendingPermissionRequestResult struct { +type PermissionRequestResult struct { // Whether the permission request was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } -type SessionPermissionsHandlePendingPermissionRequestParams struct { +type PermissionDecisionRequest struct { // Request ID of the pending permission request - RequestID string `json:"requestId"` - Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` + RequestID string `json:"requestId"` + Result PermissionDecision `json:"result"` } -type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { +type PermissionDecision struct { // The permission request was approved // // Denied because approval rules explicitly blocked it @@ -745,358 +708,360 @@ type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { // Denied by the organization's content exclusion policy // // Denied by a permission request hook registered by an extension or plugin - Kind Kind `json:"kind"` + Kind Kind `json:"kind"` // Rules that denied the request - Rules []any `json:"rules,omitempty"` + Rules []any `json:"rules,omitempty"` // Optional feedback from the user explaining the denial - Feedback *string `json:"feedback,omitempty"` + Feedback *string `json:"feedback,omitempty"` // Human-readable explanation of why the path was excluded // // Optional message from the hook explaining the denial - Message *string `json:"message,omitempty"` + Message *string `json:"message,omitempty"` // File path that triggered the exclusion - Path *string `json:"path,omitempty"` + Path *string `json:"path,omitempty"` // Whether to interrupt the current agent turn - Interrupt *bool `json:"interrupt,omitempty"` + Interrupt *bool `json:"interrupt,omitempty"` } -type SessionLogResult struct { +type LogResult struct { // The unique identifier of the emitted session event - EventID string `json:"eventId"` + EventID string `json:"eventId"` } -type SessionLogParams struct { +type LogRequest struct { // When true, the message is transient and not persisted to the session event log on disk - Ephemeral *bool `json:"ephemeral,omitempty"` - // Log severity level. Determines how the message is displayed in the timeline. Defaults to - // "info". - Level *Level `json:"level,omitempty"` + Ephemeral *bool `json:"ephemeral,omitempty"` + Level *SessionLogLevel `json:"level,omitempty"` // Human-readable message - Message string `json:"message"` + Message string `json:"message"` // Optional URL the user can open in their browser for more details - URL *string `json:"url,omitempty"` + URL *string `json:"url,omitempty"` } -type SessionShellExecResult struct { +type ShellExecResult struct { // Unique identifier for tracking streamed output - ProcessID string `json:"processId"` + ProcessID string `json:"processId"` } -type SessionShellExecParams struct { +type ShellExecRequest struct { // Shell command to execute - Command string `json:"command"` + Command string `json:"command"` // Working directory (defaults to session working directory) - Cwd *string `json:"cwd,omitempty"` + Cwd *string `json:"cwd,omitempty"` // Timeout in milliseconds (default: 30000) - Timeout *float64 `json:"timeout,omitempty"` + Timeout *int64 `json:"timeout,omitempty"` } -type SessionShellKillResult struct { +type ShellKillResult struct { // Whether the signal was sent successfully - Killed bool `json:"killed"` + Killed bool `json:"killed"` } -type SessionShellKillParams struct { +type ShellKillRequest struct { // Process identifier returned by shell.exec - ProcessID string `json:"processId"` - // Signal to send (default: SIGTERM) - Signal *Signal `json:"signal,omitempty"` + ProcessID string `json:"processId"` + Signal *ShellKillSignal `json:"signal,omitempty"` } -// Experimental: SessionHistoryCompactResult is part of an experimental API and may change or be removed. -type SessionHistoryCompactResult struct { - // Post-compaction context window usage breakdown - ContextWindow *ContextWindow `json:"contextWindow,omitempty"` +// Experimental: HistoryCompact is part of an experimental API and may change or be removed. +type HistoryCompact struct { + ContextWindow *HistoryCompactContextWindow `json:"contextWindow,omitempty"` // Number of messages removed during compaction - MessagesRemoved float64 `json:"messagesRemoved"` + MessagesRemoved int64 `json:"messagesRemoved"` // Whether compaction completed successfully - Success bool `json:"success"` + Success bool `json:"success"` // Number of tokens freed by compaction - TokensRemoved float64 `json:"tokensRemoved"` + TokensRemoved int64 `json:"tokensRemoved"` } // Post-compaction context window usage breakdown -type ContextWindow struct { +type HistoryCompactContextWindow struct { // Token count from non-system messages (user, assistant, tool) - ConversationTokens *float64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Current total tokens in the context window (system + conversation + tool definitions) - CurrentTokens float64 `json:"currentTokens"` + CurrentTokens int64 `json:"currentTokens"` // Current number of messages in the conversation - MessagesLength float64 `json:"messagesLength"` + MessagesLength int64 `json:"messagesLength"` // Token count from system message(s) - SystemTokens *float64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Maximum token count for the model's context window - TokenLimit float64 `json:"tokenLimit"` + TokenLimit int64 `json:"tokenLimit"` // Token count from tool definitions - ToolDefinitionsTokens *float64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } -// Experimental: SessionHistoryTruncateResult is part of an experimental API and may change or be removed. -type SessionHistoryTruncateResult struct { +// Experimental: HistoryTruncateResult is part of an experimental API and may change or be removed. +type HistoryTruncateResult struct { // Number of events that were removed - EventsRemoved float64 `json:"eventsRemoved"` + EventsRemoved int64 `json:"eventsRemoved"` } -// Experimental: SessionHistoryTruncateParams is part of an experimental API and may change or be removed. -type SessionHistoryTruncateParams struct { +// Experimental: HistoryTruncateRequest is part of an experimental API and may change or be removed. +type HistoryTruncateRequest struct { // Event ID to truncate to. This event and all events after it are removed from the session. - EventID string `json:"eventId"` + EventID string `json:"eventId"` } -// Experimental: SessionUsageGetMetricsResult is part of an experimental API and may change or be removed. -type SessionUsageGetMetricsResult struct { - // Aggregated code change metrics - CodeChanges CodeChanges `json:"codeChanges"` +// Experimental: UsageMetrics is part of an experimental API and may change or be removed. +type UsageMetrics struct { + CodeChanges UsageMetricsCodeChanges `json:"codeChanges"` // Currently active model identifier - CurrentModel *string `json:"currentModel,omitempty"` + CurrentModel *string `json:"currentModel,omitempty"` // Input tokens from the most recent main-agent API call - LastCallInputTokens int64 `json:"lastCallInputTokens"` + LastCallInputTokens int64 `json:"lastCallInputTokens"` // Output tokens from the most recent main-agent API call - LastCallOutputTokens int64 `json:"lastCallOutputTokens"` + LastCallOutputTokens int64 `json:"lastCallOutputTokens"` // Per-model token and request metrics, keyed by model identifier - ModelMetrics map[string]ModelMetric `json:"modelMetrics"` + ModelMetrics map[string]UsageMetricsModelMetric `json:"modelMetrics"` // Session start timestamp (epoch milliseconds) - SessionStartTime int64 `json:"sessionStartTime"` + SessionStartTime int64 `json:"sessionStartTime"` // Total time spent in model API calls (milliseconds) - TotalAPIDurationMS float64 `json:"totalApiDurationMs"` + TotalAPIDurationMS float64 `json:"totalApiDurationMs"` // Total user-initiated premium request cost across all models (may be fractional due to // multipliers) - TotalPremiumRequestCost float64 `json:"totalPremiumRequestCost"` + TotalPremiumRequestCost float64 `json:"totalPremiumRequestCost"` // Raw count of user-initiated API requests - TotalUserRequests int64 `json:"totalUserRequests"` + TotalUserRequests int64 `json:"totalUserRequests"` } // Aggregated code change metrics -type CodeChanges struct { +type UsageMetricsCodeChanges struct { // Number of distinct files modified - FilesModifiedCount int64 `json:"filesModifiedCount"` + FilesModifiedCount int64 `json:"filesModifiedCount"` // Total lines of code added - LinesAdded int64 `json:"linesAdded"` + LinesAdded int64 `json:"linesAdded"` // Total lines of code removed - LinesRemoved int64 `json:"linesRemoved"` + LinesRemoved int64 `json:"linesRemoved"` } -type ModelMetric struct { - // Request count and cost metrics for this model - Requests Requests `json:"requests"` - // Token usage metrics for this model - Usage Usage `json:"usage"` +type UsageMetricsModelMetric struct { + Requests UsageMetricsModelMetricRequests `json:"requests"` + Usage UsageMetricsModelMetricUsage `json:"usage"` } // Request count and cost metrics for this model -type Requests struct { +type UsageMetricsModelMetricRequests struct { // User-initiated premium request cost (with multiplier applied) - Cost float64 `json:"cost"` + Cost float64 `json:"cost"` // Number of API requests made with this model - Count int64 `json:"count"` + Count int64 `json:"count"` } // Token usage metrics for this model -type Usage struct { +type UsageMetricsModelMetricUsage struct { // Total tokens read from prompt cache - CacheReadTokens int64 `json:"cacheReadTokens"` + CacheReadTokens int64 `json:"cacheReadTokens"` // Total tokens written to prompt cache - CacheWriteTokens int64 `json:"cacheWriteTokens"` + CacheWriteTokens int64 `json:"cacheWriteTokens"` // Total input tokens consumed - InputTokens int64 `json:"inputTokens"` + InputTokens int64 `json:"inputTokens"` // Total output tokens produced - OutputTokens int64 `json:"outputTokens"` + OutputTokens int64 `json:"outputTokens"` + // Total output tokens used for reasoning + ReasoningTokens *int64 `json:"reasoningTokens,omitempty"` } type SessionFSReadFileResult struct { // File content as UTF-8 string - Content string `json:"content"` + Content string `json:"content"` } -type SessionFSReadFileParams struct { +type SessionFSReadFileRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -type SessionFSWriteFileParams struct { +type SessionFSWriteFileRequest struct { // Content to write - Content string `json:"content"` + Content string `json:"content"` // Optional POSIX-style mode for newly created files - Mode *float64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -type SessionFSAppendFileParams struct { +type SessionFSAppendFileRequest struct { // Content to append - Content string `json:"content"` + Content string `json:"content"` // Optional POSIX-style mode for newly created files - Mode *float64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSExistsResult struct { // Whether the path exists - Exists bool `json:"exists"` + Exists bool `json:"exists"` } -type SessionFSExistsParams struct { +type SessionFSExistsRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSStatResult struct { // ISO 8601 timestamp of creation - Birthtime string `json:"birthtime"` + Birthtime time.Time `json:"birthtime"` // Whether the path is a directory - IsDirectory bool `json:"isDirectory"` + IsDirectory bool `json:"isDirectory"` // Whether the path is a file - IsFile bool `json:"isFile"` + IsFile bool `json:"isFile"` // ISO 8601 timestamp of last modification - Mtime string `json:"mtime"` + Mtime time.Time `json:"mtime"` // File size in bytes - Size float64 `json:"size"` + Size int64 `json:"size"` } -type SessionFSStatParams struct { +type SessionFSStatRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -type SessionFSMkdirParams struct { +type SessionFSMkdirRequest struct { // Optional POSIX-style mode for newly created directories - Mode *float64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Create parent directories as needed - Recursive *bool `json:"recursive,omitempty"` + Recursive *bool `json:"recursive,omitempty"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSReaddirResult struct { // Entry names in the directory - Entries []string `json:"entries"` + Entries []string `json:"entries"` } -type SessionFSReaddirParams struct { +type SessionFSReaddirRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSReaddirWithTypesResult struct { // Directory entries with type information - Entries []Entry `json:"entries"` + Entries []SessionFSReaddirWithTypesEntry `json:"entries"` } -type Entry struct { +type SessionFSReaddirWithTypesEntry struct { // Entry name - Name string `json:"name"` - // Entry type - Type EntryType `json:"type"` + Name string `json:"name"` + Type SessionFSReaddirWithTypesEntryType `json:"type"` } -type SessionFSReaddirWithTypesParams struct { +type SessionFSReaddirWithTypesRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -type SessionFSRmParams struct { +type SessionFSRmRequest struct { // Ignore errors if the path does not exist - Force *bool `json:"force,omitempty"` + Force *bool `json:"force,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Remove directories and their contents recursively - Recursive *bool `json:"recursive,omitempty"` + Recursive *bool `json:"recursive,omitempty"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } -type SessionFSRenameParams struct { +type SessionFSRenameRequest struct { // Destination path using SessionFs conventions - Dest string `json:"dest"` + Dest string `json:"dest"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` // Source path using SessionFs conventions - Src string `json:"src"` + Src string `json:"src"` } -type FilterMappingEnum string +type MCPConfigFilterMappingString string const ( - FilterMappingEnumHiddenCharacters FilterMappingEnum = "hidden_characters" - FilterMappingEnumMarkdown FilterMappingEnum = "markdown" - FilterMappingEnumNone FilterMappingEnum = "none" + MCPConfigFilterMappingStringHiddenCharacters MCPConfigFilterMappingString = "hidden_characters" + MCPConfigFilterMappingStringMarkdown MCPConfigFilterMappingString = "markdown" + MCPConfigFilterMappingStringNone MCPConfigFilterMappingString = "none" ) -type ServerType string +type MCPConfigType string const ( - ServerTypeHTTP ServerType = "http" - ServerTypeLocal ServerType = "local" - ServerTypeSse ServerType = "sse" - ServerTypeStdio ServerType = "stdio" + MCPConfigTypeLocal MCPConfigType = "local" + MCPConfigTypeHTTP MCPConfigType = "http" + MCPConfigTypeSSE MCPConfigType = "sse" + MCPConfigTypeStdio MCPConfigType = "stdio" ) // Configuration source -type ServerSource string +// +// Configuration source: user, workspace, plugin, or builtin +type MCPServerSource string const ( - ServerSourceBuiltin ServerSource = "builtin" - ServerSourcePlugin ServerSource = "plugin" - ServerSourceUser ServerSource = "user" - ServerSourceWorkspace ServerSource = "workspace" + MCPServerSourceBuiltin MCPServerSource = "builtin" + MCPServerSourceUser MCPServerSource = "user" + MCPServerSourcePlugin MCPServerSource = "plugin" + MCPServerSourceWorkspace MCPServerSource = "workspace" +) + +// Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio) +type DiscoveredMCPServerType string + +const ( + DiscoveredMCPServerTypeHTTP DiscoveredMCPServerType = "http" + DiscoveredMCPServerTypeSSE DiscoveredMCPServerType = "sse" + DiscoveredMCPServerTypeStdio DiscoveredMCPServerType = "stdio" + DiscoveredMCPServerTypeMemory DiscoveredMCPServerType = "memory" ) // Path conventions used by this filesystem -type Conventions string +type SessionFSSetProviderConventions string const ( - ConventionsPosix Conventions = "posix" - ConventionsWindows Conventions = "windows" + SessionFSSetProviderConventionsPosix SessionFSSetProviderConventions = "posix" + SessionFSSetProviderConventionsWindows SessionFSSetProviderConventions = "windows" ) -// The current agent mode. -// -// The agent mode after switching. -// -// The mode to switch to. Valid values: "interactive", "plan", "autopilot". -type Mode string +// The agent mode. Valid values: "interactive", "plan", "autopilot". +type SessionMode string const ( - ModeAutopilot Mode = "autopilot" - ModeInteractive Mode = "interactive" - ModePlan Mode = "plan" + SessionModeAutopilot SessionMode = "autopilot" + SessionModeInteractive SessionMode = "interactive" + SessionModePlan SessionMode = "plan" ) // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured -type ServerStatus string +type MCPServerStatus string const ( - ServerStatusConnected ServerStatus = "connected" - ServerStatusNeedsAuth ServerStatus = "needs-auth" - ServerStatusNotConfigured ServerStatus = "not_configured" - ServerStatusPending ServerStatus = "pending" - ServerStatusDisabled ServerStatus = "disabled" - ServerStatusFailed ServerStatus = "failed" + MCPServerStatusConnected MCPServerStatus = "connected" + MCPServerStatusDisabled MCPServerStatus = "disabled" + MCPServerStatusFailed MCPServerStatus = "failed" + MCPServerStatusNeedsAuth MCPServerStatus = "needs-auth" + MCPServerStatusNotConfigured MCPServerStatus = "not_configured" + MCPServerStatusPending MCPServerStatus = "pending" ) // Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) type ExtensionSource string const ( - ExtensionSourceUser ExtensionSource = "user" - ExtensionSourceProject ExtensionSource = "project" + ExtensionSourceUser ExtensionSource = "user" + ExtensionSourceProject ExtensionSource = "project" ) // Current status: running, disabled, failed, or starting @@ -1105,26 +1070,26 @@ type ExtensionStatus string const ( ExtensionStatusDisabled ExtensionStatus = "disabled" ExtensionStatusFailed ExtensionStatus = "failed" - ExtensionStatusRunning ExtensionStatus = "running" - ExtensionStatusStarting ExtensionStatus = "starting" + ExtensionStatusRunning ExtensionStatus = "running" + ExtensionStatusStarting ExtensionStatus = "starting" ) // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) -type Action string +type ElicitationResponseAction string const ( - ActionAccept Action = "accept" - ActionCancel Action = "cancel" - ActionDecline Action = "decline" + ElicitationResponseActionAccept ElicitationResponseAction = "accept" + ElicitationResponseActionCancel ElicitationResponseAction = "cancel" + ElicitationResponseActionDecline ElicitationResponseAction = "decline" ) -type Format string +type UIElicitationSchemaPropertyStringFormat string const ( - FormatDate Format = "date" - FormatDateTime Format = "date-time" - FormatEmail Format = "email" - FormatURI Format = "uri" + UIElicitationSchemaPropertyStringFormatDate UIElicitationSchemaPropertyStringFormat = "date" + UIElicitationSchemaPropertyStringFormatDateTime UIElicitationSchemaPropertyStringFormat = "date-time" + UIElicitationSchemaPropertyStringFormatEmail UIElicitationSchemaPropertyStringFormat = "email" + UIElicitationSchemaPropertyStringFormatURI UIElicitationSchemaPropertyStringFormat = "uri" ) type ItemsType string @@ -1133,14 +1098,14 @@ const ( ItemsTypeString ItemsType = "string" ) -type PropertyType string +type UIElicitationSchemaPropertyNumberType string const ( - PropertyTypeArray PropertyType = "array" - PropertyTypeBoolean PropertyType = "boolean" - PropertyTypeString PropertyType = "string" - PropertyTypeInteger PropertyType = "integer" - PropertyTypeNumber PropertyType = "number" + UIElicitationSchemaPropertyNumberTypeArray UIElicitationSchemaPropertyNumberType = "array" + UIElicitationSchemaPropertyNumberTypeBoolean UIElicitationSchemaPropertyNumberType = "boolean" + UIElicitationSchemaPropertyNumberTypeInteger UIElicitationSchemaPropertyNumberType = "integer" + UIElicitationSchemaPropertyNumberTypeNumber UIElicitationSchemaPropertyNumberType = "number" + UIElicitationSchemaPropertyNumberTypeString UIElicitationSchemaPropertyNumberType = "string" ) type RequestedSchemaType string @@ -1162,43 +1127,43 @@ const ( // Log severity level. Determines how the message is displayed in the timeline. Defaults to // "info". -type Level string +type SessionLogLevel string const ( - LevelError Level = "error" - LevelInfo Level = "info" - LevelWarning Level = "warning" + SessionLogLevelError SessionLogLevel = "error" + SessionLogLevelInfo SessionLogLevel = "info" + SessionLogLevelWarning SessionLogLevel = "warning" ) // Signal to send (default: SIGTERM) -type Signal string +type ShellKillSignal string const ( - SignalSIGINT Signal = "SIGINT" - SignalSIGKILL Signal = "SIGKILL" - SignalSIGTERM Signal = "SIGTERM" + ShellKillSignalSIGINT ShellKillSignal = "SIGINT" + ShellKillSignalSIGKILL ShellKillSignal = "SIGKILL" + ShellKillSignalSIGTERM ShellKillSignal = "SIGTERM" ) // Entry type -type EntryType string +type SessionFSReaddirWithTypesEntryType string const ( - EntryTypeDirectory EntryType = "directory" - EntryTypeFile EntryType = "file" + SessionFSReaddirWithTypesEntryTypeDirectory SessionFSReaddirWithTypesEntryType = "directory" + SessionFSReaddirWithTypesEntryTypeFile SessionFSReaddirWithTypesEntryType = "file" ) -type FilterMappingUnion struct { - Enum *FilterMappingEnum - EnumMap map[string]FilterMappingEnum +type MCPConfigFilterMapping struct { + Enum *MCPConfigFilterMappingString + EnumMap map[string]MCPConfigFilterMappingString } // Tool call result (string or expanded result object) -type ResultUnion struct { - ResultResult *ResultResult - String *string +type ToolsHandlePendingToolCall struct { + String *string + ToolCallResult *ToolCallResult } -type Content struct { +type ElicitationFieldValue struct { Bool *bool Double *float64 String *string @@ -1211,12 +1176,12 @@ type serverApi struct { type ServerModelsApi serverApi -func (a *ServerModelsApi) List(ctx context.Context) (*ModelsListResult, error) { +func (a *ServerModelsApi) List(ctx context.Context) (*ModelList, error) { raw, err := a.client.Request("models.list", nil) if err != nil { return nil, err } - var result ModelsListResult + var result ModelList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1225,12 +1190,12 @@ func (a *ServerModelsApi) List(ctx context.Context) (*ModelsListResult, error) { type ServerToolsApi serverApi -func (a *ServerToolsApi) List(ctx context.Context, params *ToolsListParams) (*ToolsListResult, error) { +func (a *ServerToolsApi) List(ctx context.Context, params *ToolsListRequest) (*ToolList, error) { raw, err := a.client.Request("tools.list", params) if err != nil { return nil, err } - var result ToolsListResult + var result ToolList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1239,12 +1204,12 @@ func (a *ServerToolsApi) List(ctx context.Context, params *ToolsListParams) (*To type ServerAccountApi serverApi -func (a *ServerAccountApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult, error) { +func (a *ServerAccountApi) GetQuota(ctx context.Context) (*AccountQuota, error) { raw, err := a.client.Request("account.getQuota", nil) if err != nil { return nil, err } - var result AccountGetQuotaResult + var result AccountQuota if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1253,7 +1218,7 @@ func (a *ServerAccountApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult type ServerMcpApi serverApi -func (a *ServerMcpApi) Discover(ctx context.Context, params *MCPDiscoverParams) (*MCPDiscoverResult, error) { +func (a *ServerMcpApi) Discover(ctx context.Context, params *MCPDiscoverRequest) (*MCPDiscoverResult, error) { raw, err := a.client.Request("mcp.discover", params) if err != nil { return nil, err @@ -1267,7 +1232,7 @@ func (a *ServerMcpApi) Discover(ctx context.Context, params *MCPDiscoverParams) type ServerSessionFsApi serverApi -func (a *ServerSessionFsApi) SetProvider(ctx context.Context, params *SessionFSSetProviderParams) (*SessionFSSetProviderResult, error) { +func (a *ServerSessionFsApi) SetProvider(ctx context.Context, params *SessionFSSetProviderRequest) (*SessionFSSetProviderResult, error) { raw, err := a.client.Request("sessionFs.setProvider", params) if err != nil { return nil, err @@ -1282,7 +1247,7 @@ func (a *ServerSessionFsApi) SetProvider(ctx context.Context, params *SessionFSS // Experimental: ServerSessionsApi contains experimental APIs that may change or be removed. type ServerSessionsApi serverApi -func (a *ServerSessionsApi) Fork(ctx context.Context, params *SessionsForkParams) (*SessionsForkResult, error) { +func (a *ServerSessionsApi) Fork(ctx context.Context, params *SessionsForkRequest) (*SessionsForkResult, error) { raw, err := a.client.Request("sessions.fork", params) if err != nil { return nil, err @@ -1296,7 +1261,7 @@ func (a *ServerSessionsApi) Fork(ctx context.Context, params *SessionsForkParams // ServerRpc provides typed server-scoped RPC methods. type ServerRpc struct { - common serverApi // Reuse a single struct instead of allocating one for each service on the heap. + common serverApi // Reuse a single struct instead of allocating one for each service on the heap. Models *ServerModelsApi Tools *ServerToolsApi @@ -1306,7 +1271,7 @@ type ServerRpc struct { Sessions *ServerSessionsApi } -func (a *ServerRpc) Ping(ctx context.Context, params *PingParams) (*PingResult, error) { +func (a *ServerRpc) Ping(ctx context.Context, params *PingRequest) (*PingResult, error) { raw, err := a.common.client.Request("ping", params) if err != nil { return nil, err @@ -1331,26 +1296,26 @@ func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { } type sessionApi struct { - client *jsonrpc2.Client + client *jsonrpc2.Client sessionID string } type ModelApi sessionApi -func (a *ModelApi) GetCurrent(ctx context.Context) (*SessionModelGetCurrentResult, error) { +func (a *ModelApi) GetCurrent(ctx context.Context) (*ModelCurrent, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.model.getCurrent", req) if err != nil { return nil, err } - var result SessionModelGetCurrentResult + var result ModelCurrent if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ModelApi) SwitchTo(ctx context.Context, params *SessionModelSwitchToParams) (*SessionModelSwitchToResult, error) { +func (a *ModelApi) SwitchTo(ctx context.Context, params *ModelSwitchToRequest) (*ModelSwitchToResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["modelId"] = params.ModelID @@ -1365,7 +1330,7 @@ func (a *ModelApi) SwitchTo(ctx context.Context, params *SessionModelSwitchToPar if err != nil { return nil, err } - var result SessionModelSwitchToResult + var result ModelSwitchToResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1374,20 +1339,20 @@ func (a *ModelApi) SwitchTo(ctx context.Context, params *SessionModelSwitchToPar type ModeApi sessionApi -func (a *ModeApi) Get(ctx context.Context) (*SessionModeGetResult, error) { +func (a *ModeApi) Get(ctx context.Context) (*SessionMode, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.mode.get", req) if err != nil { return nil, err } - var result SessionModeGetResult + var result SessionMode if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ModeApi) Set(ctx context.Context, params *SessionModeSetParams) (*SessionModeSetResult, error) { +func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionMode, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["mode"] = params.Mode @@ -1396,7 +1361,7 @@ func (a *ModeApi) Set(ctx context.Context, params *SessionModeSetParams) (*Sessi if err != nil { return nil, err } - var result SessionModeSetResult + var result SessionMode if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1405,20 +1370,20 @@ func (a *ModeApi) Set(ctx context.Context, params *SessionModeSetParams) (*Sessi type PlanApi sessionApi -func (a *PlanApi) Read(ctx context.Context) (*SessionPlanReadResult, error) { +func (a *PlanApi) Read(ctx context.Context) (*Plan, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.plan.read", req) if err != nil { return nil, err } - var result SessionPlanReadResult + var result Plan if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *PlanApi) Update(ctx context.Context, params *SessionPlanUpdateParams) (*SessionPlanUpdateResult, error) { +func (a *PlanApi) Update(ctx context.Context, params *PlanUpdateRequest) (*PlanUpdateResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["content"] = params.Content @@ -1427,20 +1392,20 @@ func (a *PlanApi) Update(ctx context.Context, params *SessionPlanUpdateParams) ( if err != nil { return nil, err } - var result SessionPlanUpdateResult + var result PlanUpdateResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *PlanApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, error) { +func (a *PlanApi) Delete(ctx context.Context) (*PlanDelete, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.plan.delete", req) if err != nil { return nil, err } - var result SessionPlanDeleteResult + var result PlanDelete if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1449,20 +1414,20 @@ func (a *PlanApi) Delete(ctx context.Context) (*SessionPlanDeleteResult, error) type WorkspaceApi sessionApi -func (a *WorkspaceApi) ListFiles(ctx context.Context) (*SessionWorkspaceListFilesResult, error) { +func (a *WorkspaceApi) ListFiles(ctx context.Context) (*WorkspaceFiles, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.workspace.listFiles", req) if err != nil { return nil, err } - var result SessionWorkspaceListFilesResult + var result WorkspaceFiles if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *WorkspaceApi) ReadFile(ctx context.Context, params *SessionWorkspaceReadFileParams) (*SessionWorkspaceReadFileResult, error) { +func (a *WorkspaceApi) ReadFile(ctx context.Context, params *WorkspaceReadFileRequest) (*WorkspaceReadFileResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["path"] = params.Path @@ -1471,14 +1436,14 @@ func (a *WorkspaceApi) ReadFile(ctx context.Context, params *SessionWorkspaceRea if err != nil { return nil, err } - var result SessionWorkspaceReadFileResult + var result WorkspaceReadFileResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *WorkspaceApi) CreateFile(ctx context.Context, params *SessionWorkspaceCreateFileParams) (*SessionWorkspaceCreateFileResult, error) { +func (a *WorkspaceApi) CreateFile(ctx context.Context, params *WorkspaceCreateFileRequest) (*WorkspaceCreateFileResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["path"] = params.Path @@ -1488,7 +1453,7 @@ func (a *WorkspaceApi) CreateFile(ctx context.Context, params *SessionWorkspaceC if err != nil { return nil, err } - var result SessionWorkspaceCreateFileResult + var result WorkspaceCreateFileResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1498,7 +1463,7 @@ func (a *WorkspaceApi) CreateFile(ctx context.Context, params *SessionWorkspaceC // Experimental: FleetApi contains experimental APIs that may change or be removed. type FleetApi sessionApi -func (a *FleetApi) Start(ctx context.Context, params *SessionFleetStartParams) (*SessionFleetStartResult, error) { +func (a *FleetApi) Start(ctx context.Context, params *FleetStartRequest) (*FleetStartResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { if params.Prompt != nil { @@ -1509,7 +1474,7 @@ func (a *FleetApi) Start(ctx context.Context, params *SessionFleetStartParams) ( if err != nil { return nil, err } - var result SessionFleetStartResult + var result FleetStartResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1519,33 +1484,33 @@ func (a *FleetApi) Start(ctx context.Context, params *SessionFleetStartParams) ( // Experimental: AgentApi contains experimental APIs that may change or be removed. type AgentApi sessionApi -func (a *AgentApi) List(ctx context.Context) (*SessionAgentListResult, error) { +func (a *AgentApi) List(ctx context.Context) (*AgentList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.list", req) if err != nil { return nil, err } - var result SessionAgentListResult + var result AgentList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *AgentApi) GetCurrent(ctx context.Context) (*SessionAgentGetCurrentResult, error) { +func (a *AgentApi) GetCurrent(ctx context.Context) (*AgentCurrent, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.getCurrent", req) if err != nil { return nil, err } - var result SessionAgentGetCurrentResult + var result AgentCurrent if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *AgentApi) Select(ctx context.Context, params *SessionAgentSelectParams) (*SessionAgentSelectResult, error) { +func (a *AgentApi) Select(ctx context.Context, params *AgentSelectRequest) (*AgentSelectResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["name"] = params.Name @@ -1554,33 +1519,33 @@ func (a *AgentApi) Select(ctx context.Context, params *SessionAgentSelectParams) if err != nil { return nil, err } - var result SessionAgentSelectResult + var result AgentSelectResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *AgentApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, error) { +func (a *AgentApi) Deselect(ctx context.Context) (*AgentDeselect, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.deselect", req) if err != nil { return nil, err } - var result SessionAgentDeselectResult + var result AgentDeselect if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *AgentApi) Reload(ctx context.Context) (*SessionAgentReloadResult, error) { +func (a *AgentApi) Reload(ctx context.Context) (*AgentReload, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.agent.reload", req) if err != nil { return nil, err } - var result SessionAgentReloadResult + var result AgentReload if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1590,20 +1555,20 @@ func (a *AgentApi) Reload(ctx context.Context) (*SessionAgentReloadResult, error // Experimental: SkillsApi contains experimental APIs that may change or be removed. type SkillsApi sessionApi -func (a *SkillsApi) List(ctx context.Context) (*SessionSkillsListResult, error) { +func (a *SkillsApi) List(ctx context.Context) (*SkillList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.skills.list", req) if err != nil { return nil, err } - var result SessionSkillsListResult + var result SkillList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *SkillsApi) Enable(ctx context.Context, params *SessionSkillsEnableParams) (*SessionSkillsEnableResult, error) { +func (a *SkillsApi) Enable(ctx context.Context, params *SkillsEnableRequest) (*SkillsEnableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["name"] = params.Name @@ -1612,14 +1577,14 @@ func (a *SkillsApi) Enable(ctx context.Context, params *SessionSkillsEnableParam if err != nil { return nil, err } - var result SessionSkillsEnableResult + var result SkillsEnableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *SkillsApi) Disable(ctx context.Context, params *SessionSkillsDisableParams) (*SessionSkillsDisableResult, error) { +func (a *SkillsApi) Disable(ctx context.Context, params *SkillsDisableRequest) (*SkillsDisableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["name"] = params.Name @@ -1628,20 +1593,20 @@ func (a *SkillsApi) Disable(ctx context.Context, params *SessionSkillsDisablePar if err != nil { return nil, err } - var result SessionSkillsDisableResult + var result SkillsDisableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *SkillsApi) Reload(ctx context.Context) (*SessionSkillsReloadResult, error) { +func (a *SkillsApi) Reload(ctx context.Context) (*SkillsReload, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.skills.reload", req) if err != nil { return nil, err } - var result SessionSkillsReloadResult + var result SkillsReload if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1651,20 +1616,20 @@ func (a *SkillsApi) Reload(ctx context.Context) (*SessionSkillsReloadResult, err // Experimental: McpApi contains experimental APIs that may change or be removed. type McpApi sessionApi -func (a *McpApi) List(ctx context.Context) (*SessionMCPListResult, error) { +func (a *McpApi) List(ctx context.Context) (*MCPList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.mcp.list", req) if err != nil { return nil, err } - var result SessionMCPListResult + var result MCPList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *McpApi) Enable(ctx context.Context, params *SessionMCPEnableParams) (*SessionMCPEnableResult, error) { +func (a *McpApi) Enable(ctx context.Context, params *MCPEnableRequest) (*MCPEnableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["serverName"] = params.ServerName @@ -1673,14 +1638,14 @@ func (a *McpApi) Enable(ctx context.Context, params *SessionMCPEnableParams) (*S if err != nil { return nil, err } - var result SessionMCPEnableResult + var result MCPEnableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *McpApi) Disable(ctx context.Context, params *SessionMCPDisableParams) (*SessionMCPDisableResult, error) { +func (a *McpApi) Disable(ctx context.Context, params *MCPDisableRequest) (*MCPDisableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["serverName"] = params.ServerName @@ -1689,20 +1654,20 @@ func (a *McpApi) Disable(ctx context.Context, params *SessionMCPDisableParams) ( if err != nil { return nil, err } - var result SessionMCPDisableResult + var result MCPDisableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *McpApi) Reload(ctx context.Context) (*SessionMCPReloadResult, error) { +func (a *McpApi) Reload(ctx context.Context) (*MCPReload, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.mcp.reload", req) if err != nil { return nil, err } - var result SessionMCPReloadResult + var result MCPReload if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1712,13 +1677,13 @@ func (a *McpApi) Reload(ctx context.Context) (*SessionMCPReloadResult, error) { // Experimental: PluginsApi contains experimental APIs that may change or be removed. type PluginsApi sessionApi -func (a *PluginsApi) List(ctx context.Context) (*SessionPluginsListResult, error) { +func (a *PluginsApi) List(ctx context.Context) (*PluginList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.plugins.list", req) if err != nil { return nil, err } - var result SessionPluginsListResult + var result PluginList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1728,20 +1693,20 @@ func (a *PluginsApi) List(ctx context.Context) (*SessionPluginsListResult, error // Experimental: ExtensionsApi contains experimental APIs that may change or be removed. type ExtensionsApi sessionApi -func (a *ExtensionsApi) List(ctx context.Context) (*SessionExtensionsListResult, error) { +func (a *ExtensionsApi) List(ctx context.Context) (*ExtensionList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.extensions.list", req) if err != nil { return nil, err } - var result SessionExtensionsListResult + var result ExtensionList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ExtensionsApi) Enable(ctx context.Context, params *SessionExtensionsEnableParams) (*SessionExtensionsEnableResult, error) { +func (a *ExtensionsApi) Enable(ctx context.Context, params *ExtensionsEnableRequest) (*ExtensionsEnableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["id"] = params.ID @@ -1750,14 +1715,14 @@ func (a *ExtensionsApi) Enable(ctx context.Context, params *SessionExtensionsEna if err != nil { return nil, err } - var result SessionExtensionsEnableResult + var result ExtensionsEnableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ExtensionsApi) Disable(ctx context.Context, params *SessionExtensionsDisableParams) (*SessionExtensionsDisableResult, error) { +func (a *ExtensionsApi) Disable(ctx context.Context, params *ExtensionsDisableRequest) (*ExtensionsDisableResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["id"] = params.ID @@ -1766,20 +1731,20 @@ func (a *ExtensionsApi) Disable(ctx context.Context, params *SessionExtensionsDi if err != nil { return nil, err } - var result SessionExtensionsDisableResult + var result ExtensionsDisableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ExtensionsApi) Reload(ctx context.Context) (*SessionExtensionsReloadResult, error) { +func (a *ExtensionsApi) Reload(ctx context.Context) (*ExtensionsReload, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.extensions.reload", req) if err != nil { return nil, err } - var result SessionExtensionsReloadResult + var result ExtensionsReload if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1788,7 +1753,7 @@ func (a *ExtensionsApi) Reload(ctx context.Context) (*SessionExtensionsReloadRes type ToolsApi sessionApi -func (a *ToolsApi) HandlePendingToolCall(ctx context.Context, params *SessionToolsHandlePendingToolCallParams) (*SessionToolsHandlePendingToolCallResult, error) { +func (a *ToolsApi) HandlePendingToolCall(ctx context.Context, params *ToolsHandlePendingToolCallRequest) (*HandleToolCallResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["requestId"] = params.RequestID @@ -1803,7 +1768,7 @@ func (a *ToolsApi) HandlePendingToolCall(ctx context.Context, params *SessionToo if err != nil { return nil, err } - var result SessionToolsHandlePendingToolCallResult + var result HandleToolCallResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1812,7 +1777,7 @@ func (a *ToolsApi) HandlePendingToolCall(ctx context.Context, params *SessionToo type CommandsApi sessionApi -func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *SessionCommandsHandlePendingCommandParams) (*SessionCommandsHandlePendingCommandResult, error) { +func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *CommandsHandlePendingCommandRequest) (*CommandsHandlePendingCommandResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["requestId"] = params.RequestID @@ -1824,7 +1789,7 @@ func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *SessionC if err != nil { return nil, err } - var result SessionCommandsHandlePendingCommandResult + var result CommandsHandlePendingCommandResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1833,7 +1798,7 @@ func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *SessionC type UIApi sessionApi -func (a *UIApi) Elicitation(ctx context.Context, params *SessionUIElicitationParams) (*SessionUIElicitationResult, error) { +func (a *UIApi) Elicitation(ctx context.Context, params *UIElicitationRequest) (*UIElicitationResponse, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["message"] = params.Message @@ -1843,14 +1808,14 @@ func (a *UIApi) Elicitation(ctx context.Context, params *SessionUIElicitationPar if err != nil { return nil, err } - var result SessionUIElicitationResult + var result UIElicitationResponse if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *SessionUIHandlePendingElicitationParams) (*SessionUIHandlePendingElicitationResult, error) { +func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *HandlePendingElicitationRequest) (*UIElicitationResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["requestId"] = params.RequestID @@ -1860,7 +1825,7 @@ func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *SessionUIH if err != nil { return nil, err } - var result SessionUIHandlePendingElicitationResult + var result UIElicitationResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1869,7 +1834,7 @@ func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *SessionUIH type PermissionsApi sessionApi -func (a *PermissionsApi) HandlePendingPermissionRequest(ctx context.Context, params *SessionPermissionsHandlePendingPermissionRequestParams) (*SessionPermissionsHandlePendingPermissionRequestResult, error) { +func (a *PermissionsApi) HandlePendingPermissionRequest(ctx context.Context, params *PermissionDecisionRequest) (*PermissionRequestResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["requestId"] = params.RequestID @@ -1879,7 +1844,7 @@ func (a *PermissionsApi) HandlePendingPermissionRequest(ctx context.Context, par if err != nil { return nil, err } - var result SessionPermissionsHandlePendingPermissionRequestResult + var result PermissionRequestResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1888,7 +1853,7 @@ func (a *PermissionsApi) HandlePendingPermissionRequest(ctx context.Context, par type ShellApi sessionApi -func (a *ShellApi) Exec(ctx context.Context, params *SessionShellExecParams) (*SessionShellExecResult, error) { +func (a *ShellApi) Exec(ctx context.Context, params *ShellExecRequest) (*ShellExecResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["command"] = params.Command @@ -1903,14 +1868,14 @@ func (a *ShellApi) Exec(ctx context.Context, params *SessionShellExecParams) (*S if err != nil { return nil, err } - var result SessionShellExecResult + var result ShellExecResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *ShellApi) Kill(ctx context.Context, params *SessionShellKillParams) (*SessionShellKillResult, error) { +func (a *ShellApi) Kill(ctx context.Context, params *ShellKillRequest) (*ShellKillResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["processId"] = params.ProcessID @@ -1922,7 +1887,7 @@ func (a *ShellApi) Kill(ctx context.Context, params *SessionShellKillParams) (*S if err != nil { return nil, err } - var result SessionShellKillResult + var result ShellKillResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1932,20 +1897,20 @@ func (a *ShellApi) Kill(ctx context.Context, params *SessionShellKillParams) (*S // Experimental: HistoryApi contains experimental APIs that may change or be removed. type HistoryApi sessionApi -func (a *HistoryApi) Compact(ctx context.Context) (*SessionHistoryCompactResult, error) { +func (a *HistoryApi) Compact(ctx context.Context) (*HistoryCompact, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.history.compact", req) if err != nil { return nil, err } - var result SessionHistoryCompactResult + var result HistoryCompact if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (a *HistoryApi) Truncate(ctx context.Context, params *SessionHistoryTruncateParams) (*SessionHistoryTruncateResult, error) { +func (a *HistoryApi) Truncate(ctx context.Context, params *HistoryTruncateRequest) (*HistoryTruncateResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["eventId"] = params.EventID @@ -1954,7 +1919,7 @@ func (a *HistoryApi) Truncate(ctx context.Context, params *SessionHistoryTruncat if err != nil { return nil, err } - var result SessionHistoryTruncateResult + var result HistoryTruncateResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1964,13 +1929,13 @@ func (a *HistoryApi) Truncate(ctx context.Context, params *SessionHistoryTruncat // Experimental: UsageApi contains experimental APIs that may change or be removed. type UsageApi sessionApi -func (a *UsageApi) GetMetrics(ctx context.Context) (*SessionUsageGetMetricsResult, error) { +func (a *UsageApi) GetMetrics(ctx context.Context) (*UsageMetrics, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.usage.getMetrics", req) if err != nil { return nil, err } - var result SessionUsageGetMetricsResult + var result UsageMetrics if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1979,7 +1944,7 @@ func (a *UsageApi) GetMetrics(ctx context.Context) (*SessionUsageGetMetricsResul // SessionRpc provides typed session-scoped RPC methods. type SessionRpc struct { - common sessionApi // Reuse a single struct instead of allocating one for each service on the heap. + common sessionApi // Reuse a single struct instead of allocating one for each service on the heap. Model *ModelApi Mode *ModeApi @@ -2000,7 +1965,7 @@ type SessionRpc struct { Usage *UsageApi } -func (a *SessionRpc) Log(ctx context.Context, params *SessionLogParams) (*SessionLogResult, error) { +func (a *SessionRpc) Log(ctx context.Context, params *LogRequest) (*LogResult, error) { req := map[string]any{"sessionId": a.common.sessionID} if params != nil { req["message"] = params.Message @@ -2018,7 +1983,7 @@ func (a *SessionRpc) Log(ctx context.Context, params *SessionLogParams) (*Sessio if err != nil { return nil, err } - var result SessionLogResult + var result LogResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -2049,16 +2014,16 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { } type SessionFsHandler interface { - ReadFile(request *SessionFSReadFileParams) (*SessionFSReadFileResult, error) - WriteFile(request *SessionFSWriteFileParams) error - AppendFile(request *SessionFSAppendFileParams) error - Exists(request *SessionFSExistsParams) (*SessionFSExistsResult, error) - Stat(request *SessionFSStatParams) (*SessionFSStatResult, error) - Mkdir(request *SessionFSMkdirParams) error - Readdir(request *SessionFSReaddirParams) (*SessionFSReaddirResult, error) - ReaddirWithTypes(request *SessionFSReaddirWithTypesParams) (*SessionFSReaddirWithTypesResult, error) - Rm(request *SessionFSRmParams) error - Rename(request *SessionFSRenameParams) error + ReadFile(request *SessionFSReadFileRequest) (*SessionFSReadFileResult, error) + WriteFile(request *SessionFSWriteFileRequest) error + AppendFile(request *SessionFSAppendFileRequest) error + Exists(request *SessionFSExistsRequest) (*SessionFSExistsResult, error) + Stat(request *SessionFSStatRequest) (*SessionFSStatResult, error) + Mkdir(request *SessionFSMkdirRequest) error + Readdir(request *SessionFSReaddirRequest) (*SessionFSReaddirResult, error) + ReaddirWithTypes(request *SessionFSReaddirWithTypesRequest) (*SessionFSReaddirWithTypesResult, error) + Rm(request *SessionFSRmRequest) error + Rename(request *SessionFSRenameRequest) error } // ClientSessionApiHandlers provides all client session API handler groups for a session. @@ -2080,7 +2045,7 @@ func clientSessionHandlerError(err error) *jsonrpc2.Error { // RegisterClientSessionApiHandlers registers handlers for server-to-client session API calls. func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func(sessionID string) *ClientSessionApiHandlers) { client.SetRequestHandler("sessionFs.readFile", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSReadFileParams + var request SessionFSReadFileRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2099,7 +2064,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return raw, nil }) client.SetRequestHandler("sessionFs.writeFile", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSWriteFileParams + var request SessionFSWriteFileRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2113,7 +2078,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return json.RawMessage("null"), nil }) client.SetRequestHandler("sessionFs.appendFile", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSAppendFileParams + var request SessionFSAppendFileRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2127,7 +2092,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return json.RawMessage("null"), nil }) client.SetRequestHandler("sessionFs.exists", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSExistsParams + var request SessionFSExistsRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2146,7 +2111,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return raw, nil }) client.SetRequestHandler("sessionFs.stat", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSStatParams + var request SessionFSStatRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2165,7 +2130,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return raw, nil }) client.SetRequestHandler("sessionFs.mkdir", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSMkdirParams + var request SessionFSMkdirRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2179,7 +2144,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return json.RawMessage("null"), nil }) client.SetRequestHandler("sessionFs.readdir", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSReaddirParams + var request SessionFSReaddirRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2198,7 +2163,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return raw, nil }) client.SetRequestHandler("sessionFs.readdirWithTypes", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSReaddirWithTypesParams + var request SessionFSReaddirWithTypesRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2217,7 +2182,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return raw, nil }) client.SetRequestHandler("sessionFs.rm", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSRmParams + var request SessionFSRmRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } @@ -2231,7 +2196,7 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( return json.RawMessage("null"), nil }) client.SetRequestHandler("sessionFs.rename", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { - var request SessionFSRenameParams + var request SessionFSRenameRequest if err := json.Unmarshal(params, &request); err != nil { return nil, &jsonrpc2.Error{Code: -32602, Message: fmt.Sprintf("Invalid params: %v", err)} } diff --git a/go/rpc/result_union.go b/go/rpc/result_union.go index 6cd948b50..aabfe6553 100644 --- a/go/rpc/result_union.go +++ b/go/rpc/result_union.go @@ -2,33 +2,33 @@ package rpc import "encoding/json" -// MarshalJSON serializes ResultUnion as the appropriate JSON variant: -// a plain string when String is set, or the ResultResult object otherwise. +// MarshalJSON serializes ToolsHandlePendingToolCall as the appropriate JSON variant: +// a plain string when String is set, or the ToolCallResult object otherwise. // The generated struct has no custom marshaler, so without this the Go -// struct fields would serialize as {"ResultResult":...,"String":...} +// struct fields would serialize as {"ToolCallResult":...,"String":...} // instead of the union the server expects. -func (r ResultUnion) MarshalJSON() ([]byte, error) { +func (r ToolsHandlePendingToolCall) MarshalJSON() ([]byte, error) { if r.String != nil { return json.Marshal(*r.String) } - if r.ResultResult != nil { - return json.Marshal(*r.ResultResult) + if r.ToolCallResult != nil { + return json.Marshal(*r.ToolCallResult) } return []byte("null"), nil } -// UnmarshalJSON deserializes a JSON value into the appropriate ResultUnion variant. -func (r *ResultUnion) UnmarshalJSON(data []byte) error { +// UnmarshalJSON deserializes a JSON value into the appropriate ToolsHandlePendingToolCall variant. +func (r *ToolsHandlePendingToolCall) UnmarshalJSON(data []byte) error { // Try string first var s string if err := json.Unmarshal(data, &s); err == nil { r.String = &s return nil } - // Try ResultResult object - var rr ResultResult + // Try ToolCallResult object + var rr ToolCallResult if err := json.Unmarshal(data, &rr); err == nil { - r.ResultResult = &rr + r.ToolCallResult = &rr return nil } return nil diff --git a/go/session.go b/go/session.go index fde0d9875..d7a781f09 100644 --- a/go/session.go +++ b/go/session.go @@ -533,7 +533,7 @@ func (s *Session) executeCommandAndRespond(requestID, commandName, command, args handler, ok := s.getCommandHandler(commandName) if !ok { errMsg := fmt.Sprintf("Unknown command: %s", commandName) - s.RPC.Commands.HandlePendingCommand(ctx, &rpc.SessionCommandsHandlePendingCommandParams{ + s.RPC.Commands.HandlePendingCommand(ctx, &rpc.CommandsHandlePendingCommandRequest{ RequestID: requestID, Error: &errMsg, }) @@ -549,14 +549,14 @@ func (s *Session) executeCommandAndRespond(requestID, commandName, command, args if err := handler(cmdCtx); err != nil { errMsg := err.Error() - s.RPC.Commands.HandlePendingCommand(ctx, &rpc.SessionCommandsHandlePendingCommandParams{ + s.RPC.Commands.HandlePendingCommand(ctx, &rpc.CommandsHandlePendingCommandRequest{ RequestID: requestID, Error: &errMsg, }) return } - s.RPC.Commands.HandlePendingCommand(ctx, &rpc.SessionCommandsHandlePendingCommandParams{ + s.RPC.Commands.HandlePendingCommand(ctx, &rpc.CommandsHandlePendingCommandRequest{ RequestID: requestID, }) } @@ -588,35 +588,35 @@ func (s *Session) handleElicitationRequest(elicitCtx ElicitationContext, request result, err := handler(elicitCtx) if err != nil { // Handler failed — attempt to cancel so the request doesn't hang. - s.RPC.UI.HandlePendingElicitation(ctx, &rpc.SessionUIHandlePendingElicitationParams{ + s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ RequestID: requestID, - Result: rpc.SessionUIHandlePendingElicitationParamsResult{ - Action: rpc.ActionCancel, + Result: rpc.UIElicitationResponse{ + Action: rpc.UIElicitationActionCancel, }, }) return } - rpcContent := make(map[string]*rpc.Content) + rpcContent := make(map[string]*rpc.UIElicitationContent) for k, v := range result.Content { rpcContent[k] = toRPCContent(v) } - s.RPC.UI.HandlePendingElicitation(ctx, &rpc.SessionUIHandlePendingElicitationParams{ + s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ RequestID: requestID, - Result: rpc.SessionUIHandlePendingElicitationParamsResult{ - Action: rpc.Action(result.Action), + Result: rpc.UIElicitationResponse{ + Action: rpc.UIElicitationAction(result.Action), Content: rpcContent, }, }) } -// toRPCContent converts an arbitrary value to a *rpc.Content for elicitation responses. -func toRPCContent(v any) *rpc.Content { +// toRPCContent converts an arbitrary value to a *rpc.UIElicitationContent for elicitation responses. +func toRPCContent(v any) *rpc.UIElicitationContent { if v == nil { return nil } - c := &rpc.Content{} + c := &rpc.UIElicitationContent{} switch val := v.(type) { case bool: c.Bool = &val @@ -679,11 +679,11 @@ func (s *Session) assertElicitation() error { } // Elicitation shows a generic elicitation dialog with a custom schema. -func (ui *SessionUI) Elicitation(ctx context.Context, message string, requestedSchema rpc.RequestedSchema) (*ElicitationResult, error) { +func (ui *SessionUI) Elicitation(ctx context.Context, message string, requestedSchema rpc.UIElicitationSchema) (*ElicitationResult, error) { if err := ui.session.assertElicitation(); err != nil { return nil, err } - rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.SessionUIElicitationParams{ + rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, RequestedSchema: requestedSchema, }) @@ -699,14 +699,14 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err := ui.session.assertElicitation(); err != nil { return false, err } - defaultTrue := &rpc.Content{Bool: Bool(true)} - rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.SessionUIElicitationParams{ + defaultTrue := &rpc.UIElicitationContent{Bool: Bool(true)} + rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, - RequestedSchema: rpc.RequestedSchema{ + RequestedSchema: rpc.UIElicitationSchema{ Type: rpc.RequestedSchemaTypeObject, - Properties: map[string]rpc.Property{ + Properties: map[string]rpc.UIElicitationSchemaProperty{ "confirmed": { - Type: rpc.PropertyTypeBoolean, + Type: rpc.UIElicitationSchemaPropertyNumberTypeBoolean, Default: defaultTrue, }, }, @@ -716,7 +716,7 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err != nil { return false, err } - if rpcResult.Action == rpc.ActionAccept { + if rpcResult.Action == rpc.UIElicitationActionAccept { if c, ok := rpcResult.Content["confirmed"]; ok && c != nil && c.Bool != nil { return *c.Bool, nil } @@ -730,13 +730,13 @@ func (ui *SessionUI) Select(ctx context.Context, message string, options []strin if err := ui.session.assertElicitation(); err != nil { return "", false, err } - rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.SessionUIElicitationParams{ + rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, - RequestedSchema: rpc.RequestedSchema{ + RequestedSchema: rpc.UIElicitationSchema{ Type: rpc.RequestedSchemaTypeObject, - Properties: map[string]rpc.Property{ + Properties: map[string]rpc.UIElicitationSchemaProperty{ "selection": { - Type: rpc.PropertyTypeString, + Type: rpc.UIElicitationSchemaPropertyNumberTypeString, Enum: options, }, }, @@ -746,7 +746,7 @@ func (ui *SessionUI) Select(ctx context.Context, message string, options []strin if err != nil { return "", false, err } - if rpcResult.Action == rpc.ActionAccept { + if rpcResult.Action == rpc.UIElicitationActionAccept { if c, ok := rpcResult.Content["selection"]; ok && c != nil && c.String != nil { return *c.String, true, nil } @@ -760,7 +760,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio if err := ui.session.assertElicitation(); err != nil { return "", false, err } - prop := rpc.Property{Type: rpc.PropertyTypeString} + prop := rpc.UIElicitationSchemaProperty{Type: rpc.UIElicitationSchemaPropertyNumberTypeString} if opts != nil { if opts.Title != "" { prop.Title = &opts.Title @@ -777,18 +777,18 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio prop.MaxLength = &f } if opts.Format != "" { - format := rpc.Format(opts.Format) + format := rpc.UIElicitationSchemaPropertyStringFormat(opts.Format) prop.Format = &format } if opts.Default != "" { - prop.Default = &rpc.Content{String: &opts.Default} + prop.Default = &rpc.UIElicitationContent{String: &opts.Default} } } - rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.SessionUIElicitationParams{ + rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, - RequestedSchema: rpc.RequestedSchema{ + RequestedSchema: rpc.UIElicitationSchema{ Type: rpc.RequestedSchemaTypeObject, - Properties: map[string]rpc.Property{ + Properties: map[string]rpc.UIElicitationSchemaProperty{ "value": prop, }, Required: []string{"value"}, @@ -797,7 +797,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio if err != nil { return "", false, err } - if rpcResult.Action == rpc.ActionAccept { + if rpcResult.Action == rpc.UIElicitationActionAccept { if c, ok := rpcResult.Content["value"]; ok && c != nil && c.String != nil { return *c.String, true, nil } @@ -806,7 +806,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio } // fromRPCElicitationResult converts the RPC result to the SDK ElicitationResult. -func fromRPCElicitationResult(r *rpc.SessionUIElicitationResult) *ElicitationResult { +func fromRPCElicitationResult(r *rpc.UIElicitationResponse) *ElicitationResult { if r == nil { return nil } @@ -965,7 +965,7 @@ func (s *Session) executeToolAndRespond(requestID, toolName, toolCallID string, defer func() { if r := recover(); r != nil { errMsg := fmt.Sprintf("tool panic: %v", r) - s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.SessionToolsHandlePendingToolCallParams{ + s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.ToolsHandlePendingToolCallRequest{ RequestID: requestID, Error: &errMsg, }) @@ -983,7 +983,7 @@ func (s *Session) executeToolAndRespond(requestID, toolName, toolCallID string, result, err := handler(invocation) if err != nil { errMsg := err.Error() - s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.SessionToolsHandlePendingToolCallParams{ + s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.ToolsHandlePendingToolCallRequest{ RequestID: requestID, Error: &errMsg, }) @@ -1005,17 +1005,17 @@ func (s *Session) executeToolAndRespond(requestID, toolName, toolCallID string, } } - rpcResult := rpc.ResultUnion{ - ResultResult: &rpc.ResultResult{ + rpcResult := rpc.ToolsHandlePendingToolCall{ + ToolCallResult: &rpc.ToolCallResult{ TextResultForLlm: textResultForLLM, ToolTelemetry: result.ToolTelemetry, ResultType: &effectiveResultType, }, } if result.Error != "" { - rpcResult.ResultResult.Error = &result.Error + rpcResult.ToolCallResult.Error = &result.Error } - s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.SessionToolsHandlePendingToolCallParams{ + s.RPC.Tools.HandlePendingToolCall(ctx, &rpc.ToolsHandlePendingToolCallRequest{ RequestID: requestID, Result: &rpcResult, }) @@ -1025,9 +1025,9 @@ func (s *Session) executeToolAndRespond(requestID, toolName, toolCallID string, func (s *Session) executePermissionAndRespond(requestID string, permissionRequest PermissionRequest, handler PermissionHandlerFunc) { defer func() { if r := recover(); r != nil { - s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.SessionPermissionsHandlePendingPermissionRequestParams{ + s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.PermissionDecisionRequest{ RequestID: requestID, - Result: rpc.SessionPermissionsHandlePendingPermissionRequestParamsResult{ + Result: rpc.PermissionDecision{ Kind: rpc.KindDeniedNoApprovalRuleAndCouldNotRequestFromUser, }, }) @@ -1040,9 +1040,9 @@ func (s *Session) executePermissionAndRespond(requestID string, permissionReques result, err := handler(permissionRequest, invocation) if err != nil { - s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.SessionPermissionsHandlePendingPermissionRequestParams{ + s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.PermissionDecisionRequest{ RequestID: requestID, - Result: rpc.SessionPermissionsHandlePendingPermissionRequestParamsResult{ + Result: rpc.PermissionDecision{ Kind: rpc.KindDeniedNoApprovalRuleAndCouldNotRequestFromUser, }, }) @@ -1052,9 +1052,9 @@ func (s *Session) executePermissionAndRespond(requestID string, permissionReques return } - s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.SessionPermissionsHandlePendingPermissionRequestParams{ + s.RPC.Permissions.HandlePendingPermissionRequest(context.Background(), &rpc.PermissionDecisionRequest{ RequestID: requestID, - Result: rpc.SessionPermissionsHandlePendingPermissionRequestParamsResult{ + Result: rpc.PermissionDecision{ Kind: rpc.Kind(result.Kind), Rules: result.Rules, Feedback: nil, @@ -1209,7 +1209,7 @@ type SetModelOptions struct { // log.Printf("Failed to set model: %v", err) // } func (s *Session) SetModel(ctx context.Context, model string, opts *SetModelOptions) error { - params := &rpc.SessionModelSwitchToParams{ModelID: model} + params := &rpc.ModelSwitchToRequest{ModelID: model} if opts != nil { params.ReasoningEffort = opts.ReasoningEffort params.ModelCapabilities = opts.ModelCapabilities @@ -1224,9 +1224,9 @@ func (s *Session) SetModel(ctx context.Context, model string, opts *SetModelOpti // LogOptions configures optional parameters for [Session.Log]. type LogOptions struct { - // Level sets the log severity. Valid values are [rpc.LevelInfo] (default), - // [rpc.LevelWarning], and [rpc.LevelError]. - Level rpc.Level + // Level sets the log severity. Valid values are [rpc.SessionLogLevelInfo] (default), + // [rpc.SessionLogLevelWarning], and [rpc.SessionLogLevelError]. + Level rpc.SessionLogLevel // Ephemeral marks the message as transient so it is not persisted // to the session event log on disk. When nil the server decides the // default; set to a non-nil value to explicitly control persistence. @@ -1245,12 +1245,12 @@ type LogOptions struct { // session.Log(ctx, "Processing started") // // // Warning with options -// session.Log(ctx, "Rate limit approaching", &copilot.LogOptions{Level: rpc.LevelWarning}) +// session.Log(ctx, "Rate limit approaching", &copilot.LogOptions{Level: rpc.SessionLogLevelWarning}) // // // Ephemeral message (not persisted) // session.Log(ctx, "Working...", &copilot.LogOptions{Ephemeral: copilot.Bool(true)}) func (s *Session) Log(ctx context.Context, message string, opts *LogOptions) error { - params := &rpc.SessionLogParams{Message: message} + params := &rpc.LogRequest{Message: message} if opts != nil { if opts.Level != "" { diff --git a/go/session_test.go b/go/session_test.go index 7f22028db..d247b32bf 100644 --- a/go/session_test.go +++ b/go/session_test.go @@ -403,7 +403,7 @@ func TestSession_Capabilities(t *testing.T) { session.dispatchEvent(SessionEvent{ Type: SessionEventTypeCapabilitiesChanged, Data: &CapabilitiesChangedData{ - UI: &CapabilitiesChangedDataUI{Elicitation: &elicitTrue}, + UI: &CapabilitiesChangedUi{Elicitation: &elicitTrue}, }, }) @@ -420,7 +420,7 @@ func TestSession_Capabilities(t *testing.T) { session.dispatchEvent(SessionEvent{ Type: SessionEventTypeCapabilitiesChanged, Data: &CapabilitiesChangedData{ - UI: &CapabilitiesChangedDataUI{Elicitation: &elicitFalse}, + UI: &CapabilitiesChangedUi{Elicitation: &elicitFalse}, }, }) diff --git a/go/types.go b/go/types.go index 568bcc1b9..0e0370ed2 100644 --- a/go/types.go +++ b/go/types.go @@ -474,7 +474,7 @@ type SessionFsConfig struct { // session-scoped files such as events, checkpoints, and temp files. SessionStatePath string // Conventions identifies the path conventions used by this filesystem provider. - Conventions rpc.Conventions + Conventions rpc.SessionFSSetProviderConventions } // SessionConfig configures a new session diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index 1733e5cd9..b6d356e7b 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -20,14 +20,14 @@ export interface PingResult { protocolVersion: number; } -export interface PingParams { +export interface PingRequest { /** * Optional message to echo back */ message?: string; } -export interface ModelsListResult { +export interface ModelList { /** * List of available models with full metadata */ @@ -77,59 +77,56 @@ export interface ModelsListResult { * Model capabilities and limits */ export interface ModelCapabilities { - supports: ModelCapabilitiesSupports; - limits: ModelCapabilitiesLimits; -} -/** - * Feature flags indicating what the model supports - */ -export interface ModelCapabilitiesSupports { - /** - * Whether this model supports vision/image input - */ - vision?: boolean; - /** - * Whether this model supports reasoning effort configuration - */ - reasoningEffort?: boolean; -} -/** - * Token limits for prompts, outputs, and context window - */ -export interface ModelCapabilitiesLimits { - /** - * Maximum number of prompt/input tokens - */ - max_prompt_tokens?: number; - /** - * Maximum number of output/completion tokens - */ - max_output_tokens?: number; /** - * Maximum total context window size in tokens + * Feature flags indicating what the model supports */ - max_context_window_tokens: number; - vision?: ModelCapabilitiesLimitsVision; -} -/** - * Vision-specific limits - */ -export interface ModelCapabilitiesLimitsVision { - /** - * MIME types the model accepts - */ - supported_media_types: string[]; - /** - * Maximum number of images per prompt - */ - max_prompt_images: number; + supports: { + /** + * Whether this model supports vision/image input + */ + vision?: boolean; + /** + * Whether this model supports reasoning effort configuration + */ + reasoningEffort?: boolean; + }; /** - * Maximum image size in bytes + * Token limits for prompts, outputs, and context window */ - max_prompt_image_size: number; + limits: { + /** + * Maximum number of prompt/input tokens + */ + max_prompt_tokens?: number; + /** + * Maximum number of output/completion tokens + */ + max_output_tokens?: number; + /** + * Maximum total context window size in tokens + */ + max_context_window_tokens: number; + /** + * Vision-specific limits + */ + vision?: { + /** + * MIME types the model accepts + */ + supported_media_types: string[]; + /** + * Maximum number of images per prompt + */ + max_prompt_images: number; + /** + * Maximum image size in bytes + */ + max_prompt_image_size: number; + }; + }; } -export interface ToolsListResult { +export interface ToolList { /** * List of available built-in tools with metadata */ @@ -159,14 +156,14 @@ export interface ToolsListResult { }[]; } -export interface ToolsListParams { +export interface ToolsListRequest { /** * Optional model ID — when provided, the returned tool list reflects model-specific overrides */ model?: string; } -export interface AccountGetQuotaResult { +export interface AccountQuota { /** * Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) */ @@ -200,7 +197,7 @@ export interface AccountGetQuotaResult { }; } -export interface McpConfigListResult { +export interface McpConfigList { /** * All MCP servers from user config, keyed by name */ @@ -221,6 +218,9 @@ export interface McpConfigListResult { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; command: string; args: string[]; @@ -241,6 +241,9 @@ export interface McpConfigListResult { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; url: string; headers?: { @@ -252,7 +255,7 @@ export interface McpConfigListResult { }; } -export interface McpConfigAddParams { +export interface McpConfigAddRequest { /** * Unique name for the MCP server */ @@ -273,6 +276,9 @@ export interface McpConfigAddParams { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; command: string; args: string[]; @@ -293,6 +299,9 @@ export interface McpConfigAddParams { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; url: string; headers?: { @@ -303,7 +312,7 @@ export interface McpConfigAddParams { }; } -export interface McpConfigUpdateParams { +export interface McpConfigUpdateRequest { /** * Name of the MCP server to update */ @@ -324,6 +333,9 @@ export interface McpConfigUpdateParams { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; command: string; args: string[]; @@ -344,6 +356,9 @@ export interface McpConfigUpdateParams { [k: string]: "none" | "markdown" | "hidden_characters"; } | ("none" | "markdown" | "hidden_characters"); + /** + * Timeout in milliseconds for tool calls to this server. + */ timeout?: number; url: string; headers?: { @@ -354,7 +369,7 @@ export interface McpConfigUpdateParams { }; } -export interface McpConfigRemoveParams { +export interface McpConfigRemoveRequest { /** * Name of the MCP server to remove */ @@ -373,9 +388,9 @@ export interface DiscoveredMcpServer { */ name: string; /** - * Server type: local, stdio, http, or sse + * Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio) */ - type?: string; + type?: "stdio" | "http" | "sse" | "memory"; /** * Configuration source */ @@ -386,7 +401,7 @@ export interface DiscoveredMcpServer { enabled: boolean; } -export interface McpDiscoverParams { +export interface McpDiscoverRequest { /** * Working directory used as context for discovery (e.g., plugin resolution) */ @@ -400,7 +415,7 @@ export interface SessionFsSetProviderResult { success: boolean; } -export interface SessionFsSetProviderParams { +export interface SessionFsSetProviderRequest { /** * Initial working directory for sessions */ @@ -424,7 +439,7 @@ export interface SessionsForkResult { } /** @experimental */ -export interface SessionsForkParams { +export interface SessionsForkRequest { /** * Source session ID to fork from */ @@ -435,28 +450,28 @@ export interface SessionsForkParams { toEventId?: string; } -export interface SessionModelGetCurrentResult { +export interface ModelCurrent { /** * Currently active model identifier */ modelId?: string; } -export interface SessionModelGetCurrentParams { +export interface SessionModelGetCurrentRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionModelSwitchToResult { +export interface ModelSwitchToResult { /** * Currently active model identifier after the switch */ modelId?: string; } -export interface SessionModelSwitchToParams { +export interface ModelSwitchToRequest { /** * Target session identifier */ @@ -475,76 +490,62 @@ export interface SessionModelSwitchToParams { * Override individual model capabilities resolved by the runtime */ export interface ModelCapabilitiesOverride { - supports?: ModelCapabilitiesOverrideSupports; - limits?: ModelCapabilitiesOverrideLimits; -} -/** - * Feature flags indicating what the model supports - */ -export interface ModelCapabilitiesOverrideSupports { - vision?: boolean; - reasoningEffort?: boolean; -} -/** - * Token limits for prompts, outputs, and context window - */ -export interface ModelCapabilitiesOverrideLimits { - max_prompt_tokens?: number; - max_output_tokens?: number; - /** - * Maximum total context window size in tokens - */ - max_context_window_tokens?: number; - vision?: ModelCapabilitiesOverrideLimitsVision; -} -export interface ModelCapabilitiesOverrideLimitsVision { - /** - * MIME types the model accepts - */ - supported_media_types?: string[]; /** - * Maximum number of images per prompt + * Feature flags indicating what the model supports */ - max_prompt_images?: number; + supports?: { + vision?: boolean; + reasoningEffort?: boolean; + }; /** - * Maximum image size in bytes + * Token limits for prompts, outputs, and context window */ - max_prompt_image_size?: number; + limits?: { + max_prompt_tokens?: number; + max_output_tokens?: number; + /** + * Maximum total context window size in tokens + */ + max_context_window_tokens?: number; + vision?: { + /** + * MIME types the model accepts + */ + supported_media_types?: string[]; + /** + * Maximum number of images per prompt + */ + max_prompt_images?: number; + /** + * Maximum image size in bytes + */ + max_prompt_image_size?: number; + }; + }; } -export interface SessionModeGetResult { - /** - * The current agent mode. - */ - mode: "interactive" | "plan" | "autopilot"; -} +/** + * The agent mode. Valid values: "interactive", "plan", "autopilot". + */ +export type SessionMode = "interactive" | "plan" | "autopilot"; -export interface SessionModeGetParams { +export interface SessionModeGetRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionModeSetResult { - /** - * The agent mode after switching. - */ - mode: "interactive" | "plan" | "autopilot"; -} -export interface SessionModeSetParams { +export interface ModeSetRequest { /** * Target session identifier */ sessionId: string; - /** - * The mode to switch to. Valid values: "interactive", "plan", "autopilot". - */ - mode: "interactive" | "plan" | "autopilot"; + mode: SessionMode; } -export interface SessionPlanReadResult { +export interface Plan { /** * Whether the plan file exists in the workspace */ @@ -559,16 +560,16 @@ export interface SessionPlanReadResult { path: string | null; } -export interface SessionPlanReadParams { +export interface SessionPlanReadRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionPlanUpdateResult {} +export interface PlanUpdateResult {} -export interface SessionPlanUpdateParams { +export interface PlanUpdateRequest { /** * Target session identifier */ @@ -579,37 +580,37 @@ export interface SessionPlanUpdateParams { content: string; } -export interface SessionPlanDeleteResult {} +export interface PlanDelete {} -export interface SessionPlanDeleteParams { +export interface SessionPlanDeleteRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionWorkspaceListFilesResult { +export interface WorkspaceFiles { /** * Relative file paths in the workspace files directory */ files: string[]; } -export interface SessionWorkspaceListFilesParams { +export interface SessionWorkspaceListFilesRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionWorkspaceReadFileResult { +export interface WorkspaceReadFileResult { /** * File content as a UTF-8 string */ content: string; } -export interface SessionWorkspaceReadFileParams { +export interface WorkspaceReadFileRequest { /** * Target session identifier */ @@ -620,9 +621,9 @@ export interface SessionWorkspaceReadFileParams { path: string; } -export interface SessionWorkspaceCreateFileResult {} +export interface WorkspaceCreateFileResult {} -export interface SessionWorkspaceCreateFileParams { +export interface WorkspaceCreateFileRequest { /** * Target session identifier */ @@ -638,7 +639,7 @@ export interface SessionWorkspaceCreateFileParams { } /** @experimental */ -export interface SessionFleetStartResult { +export interface FleetStartResult { /** * Whether fleet mode was successfully activated */ @@ -646,7 +647,7 @@ export interface SessionFleetStartResult { } /** @experimental */ -export interface SessionFleetStartParams { +export interface FleetStartRequest { /** * Target session identifier */ @@ -658,7 +659,7 @@ export interface SessionFleetStartParams { } /** @experimental */ -export interface SessionAgentListResult { +export interface AgentList { /** * Available custom agents */ @@ -679,7 +680,7 @@ export interface SessionAgentListResult { } /** @experimental */ -export interface SessionAgentListParams { +export interface SessionAgentListRequest { /** * Target session identifier */ @@ -687,7 +688,7 @@ export interface SessionAgentListParams { } /** @experimental */ -export interface SessionAgentGetCurrentResult { +export interface AgentCurrent { /** * Currently selected custom agent, or null if using the default agent */ @@ -708,7 +709,7 @@ export interface SessionAgentGetCurrentResult { } /** @experimental */ -export interface SessionAgentGetCurrentParams { +export interface SessionAgentGetCurrentRequest { /** * Target session identifier */ @@ -716,7 +717,7 @@ export interface SessionAgentGetCurrentParams { } /** @experimental */ -export interface SessionAgentSelectResult { +export interface AgentSelectResult { /** * The newly selected custom agent */ @@ -737,7 +738,7 @@ export interface SessionAgentSelectResult { } /** @experimental */ -export interface SessionAgentSelectParams { +export interface AgentSelectRequest { /** * Target session identifier */ @@ -749,10 +750,10 @@ export interface SessionAgentSelectParams { } /** @experimental */ -export interface SessionAgentDeselectResult {} +export interface AgentDeselect {} /** @experimental */ -export interface SessionAgentDeselectParams { +export interface SessionAgentDeselectRequest { /** * Target session identifier */ @@ -760,7 +761,7 @@ export interface SessionAgentDeselectParams { } /** @experimental */ -export interface SessionAgentReloadResult { +export interface AgentReload { /** * Reloaded custom agents */ @@ -781,7 +782,7 @@ export interface SessionAgentReloadResult { } /** @experimental */ -export interface SessionAgentReloadParams { +export interface SessionAgentReloadRequest { /** * Target session identifier */ @@ -789,7 +790,7 @@ export interface SessionAgentReloadParams { } /** @experimental */ -export interface SessionSkillsListResult { +export interface SkillList { /** * Available skills */ @@ -822,7 +823,7 @@ export interface SessionSkillsListResult { } /** @experimental */ -export interface SessionSkillsListParams { +export interface SessionSkillsListRequest { /** * Target session identifier */ @@ -830,10 +831,10 @@ export interface SessionSkillsListParams { } /** @experimental */ -export interface SessionSkillsEnableResult {} +export interface SkillsEnableResult {} /** @experimental */ -export interface SessionSkillsEnableParams { +export interface SkillsEnableRequest { /** * Target session identifier */ @@ -845,10 +846,10 @@ export interface SessionSkillsEnableParams { } /** @experimental */ -export interface SessionSkillsDisableResult {} +export interface SkillsDisableResult {} /** @experimental */ -export interface SessionSkillsDisableParams { +export interface SkillsDisableRequest { /** * Target session identifier */ @@ -860,10 +861,10 @@ export interface SessionSkillsDisableParams { } /** @experimental */ -export interface SessionSkillsReloadResult {} +export interface SkillsReload {} /** @experimental */ -export interface SessionSkillsReloadParams { +export interface SessionSkillsReloadRequest { /** * Target session identifier */ @@ -871,7 +872,7 @@ export interface SessionSkillsReloadParams { } /** @experimental */ -export interface SessionMcpListResult { +export interface McpList { /** * Configured MCP servers */ @@ -887,7 +888,7 @@ export interface SessionMcpListResult { /** * Configuration source: user, workspace, plugin, or builtin */ - source?: string; + source?: "user" | "workspace" | "plugin" | "builtin"; /** * Error message if the server failed to connect */ @@ -896,7 +897,7 @@ export interface SessionMcpListResult { } /** @experimental */ -export interface SessionMcpListParams { +export interface SessionMcpListRequest { /** * Target session identifier */ @@ -904,10 +905,10 @@ export interface SessionMcpListParams { } /** @experimental */ -export interface SessionMcpEnableResult {} +export interface McpEnableResult {} /** @experimental */ -export interface SessionMcpEnableParams { +export interface McpEnableRequest { /** * Target session identifier */ @@ -919,10 +920,10 @@ export interface SessionMcpEnableParams { } /** @experimental */ -export interface SessionMcpDisableResult {} +export interface McpDisableResult {} /** @experimental */ -export interface SessionMcpDisableParams { +export interface McpDisableRequest { /** * Target session identifier */ @@ -934,10 +935,10 @@ export interface SessionMcpDisableParams { } /** @experimental */ -export interface SessionMcpReloadResult {} +export interface McpReload {} /** @experimental */ -export interface SessionMcpReloadParams { +export interface SessionMcpReloadRequest { /** * Target session identifier */ @@ -945,7 +946,7 @@ export interface SessionMcpReloadParams { } /** @experimental */ -export interface SessionPluginsListResult { +export interface PluginList { /** * Installed plugins */ @@ -970,7 +971,7 @@ export interface SessionPluginsListResult { } /** @experimental */ -export interface SessionPluginsListParams { +export interface SessionPluginsListRequest { /** * Target session identifier */ @@ -978,7 +979,7 @@ export interface SessionPluginsListParams { } /** @experimental */ -export interface SessionExtensionsListResult { +export interface ExtensionList { /** * Discovered extensions and their current status */ @@ -1007,7 +1008,7 @@ export interface SessionExtensionsListResult { } /** @experimental */ -export interface SessionExtensionsListParams { +export interface SessionExtensionsListRequest { /** * Target session identifier */ @@ -1015,10 +1016,10 @@ export interface SessionExtensionsListParams { } /** @experimental */ -export interface SessionExtensionsEnableResult {} +export interface ExtensionsEnableResult {} /** @experimental */ -export interface SessionExtensionsEnableParams { +export interface ExtensionsEnableRequest { /** * Target session identifier */ @@ -1030,10 +1031,10 @@ export interface SessionExtensionsEnableParams { } /** @experimental */ -export interface SessionExtensionsDisableResult {} +export interface ExtensionsDisableResult {} /** @experimental */ -export interface SessionExtensionsDisableParams { +export interface ExtensionsDisableRequest { /** * Target session identifier */ @@ -1045,24 +1046,24 @@ export interface SessionExtensionsDisableParams { } /** @experimental */ -export interface SessionExtensionsReloadResult {} +export interface ExtensionsReload {} /** @experimental */ -export interface SessionExtensionsReloadParams { +export interface SessionExtensionsReloadRequest { /** * Target session identifier */ sessionId: string; } -export interface SessionToolsHandlePendingToolCallResult { +export interface HandleToolCallResult { /** * Whether the tool call result was handled successfully */ success: boolean; } -export interface SessionToolsHandlePendingToolCallParams { +export interface ToolsHandlePendingToolCallRequest { /** * Target session identifier */ @@ -1074,42 +1075,41 @@ export interface SessionToolsHandlePendingToolCallParams { /** * Tool call result (string or expanded result object) */ - result?: - | string - | { - /** - * Text result to send back to the LLM - */ - textResultForLlm: string; - /** - * Type of the tool result - */ - resultType?: string; - /** - * Error message if the tool call failed - */ - error?: string; - /** - * Telemetry data from tool execution - */ - toolTelemetry?: { - [k: string]: unknown; - }; - }; + result?: string | ToolCallResult; /** * Error message if the tool call failed */ error?: string; } +export interface ToolCallResult { + /** + * Text result to send back to the LLM + */ + textResultForLlm: string; + /** + * Type of the tool result + */ + resultType?: string; + /** + * Error message if the tool call failed + */ + error?: string; + /** + * Telemetry data from tool execution + */ + toolTelemetry?: { + [k: string]: unknown; + }; +} -export interface SessionCommandsHandlePendingCommandResult { +export interface CommandsHandlePendingCommandResult { /** * Whether the command was handled successfully */ success: boolean; } -export interface SessionCommandsHandlePendingCommandParams { +export interface CommandsHandlePendingCommandRequest { /** * Target session identifier */ @@ -1124,20 +1124,26 @@ export interface SessionCommandsHandlePendingCommandParams { error?: string; } -export interface SessionUiElicitationResult { - /** - * The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - */ - action: "accept" | "decline" | "cancel"; - /** - * The form values submitted by the user (present when action is 'accept') - */ - content?: { - [k: string]: string | number | boolean | string[]; - }; +/** + * The user's response: accept (submitted), decline (rejected), or cancel (dismissed) + */ +export type ElicitationResponseAction = "accept" | "decline" | "cancel"; +export type ElicitationFieldValue = string | number | boolean | string[]; +/** + * The elicitation response (accept with form values, decline, or cancel) + */ +export interface UiElicitationResponse { + action: ElicitationResponseAction; + content?: ElicitationResponseContent; +} +/** + * The form values submitted by the user (present when action is 'accept') + */ +export interface ElicitationResponseContent { + [k: string]: ElicitationFieldValue; } -export interface SessionUiElicitationParams { +export interface UiElicitationRequest { /** * Target session identifier */ @@ -1159,59 +1165,17 @@ export interface SessionUiElicitationParams { */ properties: { [k: string]: - | { - type: "string"; - title?: string; - description?: string; - enum: string[]; - enumNames?: string[]; - default?: string; - } - | { - type: "string"; - title?: string; - description?: string; - oneOf: { - const: string; - title: string; - }[]; - default?: string; - } - | { - type: "array"; - title?: string; - description?: string; - minItems?: number; - maxItems?: number; - items: { - type: "string"; - enum: string[]; - }; - default?: string[]; - } - | { - type: "array"; - title?: string; - description?: string; - minItems?: number; - maxItems?: number; - items: { - anyOf: { - const: string; - title: string; - }[]; - }; - default?: string[]; - } + | ElicitationStringEnumField + | ElicitationStringOneOfField + | ElicitationArrayEnumField + | ElicitationArrayAnyOfField | { type: "boolean"; - title?: string; description?: string; default?: boolean; } | { type: "string"; - title?: string; description?: string; minLength?: number; maxLength?: number; @@ -1220,7 +1184,6 @@ export interface SessionUiElicitationParams { } | { type: "number" | "integer"; - title?: string; description?: string; minimum?: number; maximum?: number; @@ -1233,15 +1196,53 @@ export interface SessionUiElicitationParams { required?: string[]; }; } +export interface ElicitationStringEnumField { + type: "string"; + description?: string; + enum: string[]; + enumNames?: string[]; + default?: string; +} +export interface ElicitationStringOneOfField { + type: "string"; + description?: string; + oneOf: { + const: string; + }[]; + default?: string; +} +export interface ElicitationArrayEnumField { + type: "array"; + description?: string; + minItems?: number; + maxItems?: number; + items: { + type: "string"; + enum: string[]; + }; + default?: string[]; +} +export interface ElicitationArrayAnyOfField { + type: "array"; + description?: string; + minItems?: number; + maxItems?: number; + items: { + anyOf: { + const: string; + }[]; + }; + default?: string[]; +} -export interface SessionUiHandlePendingElicitationResult { +export interface UiElicitationResult { /** * Whether the response was accepted. False if the request was already resolved by another client. */ success: boolean; } -export interface SessionUiHandlePendingElicitationParams { +export interface HandlePendingElicitationRequest { /** * Target session identifier */ @@ -1250,31 +1251,79 @@ export interface SessionUiHandlePendingElicitationParams { * The unique request ID from the elicitation.requested event */ requestId: string; - /** - * The elicitation response (accept with form values, decline, or cancel) - */ - result: { - /** - * The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - */ - action: "accept" | "decline" | "cancel"; - /** - * The form values submitted by the user (present when action is 'accept') - */ - content?: { - [k: string]: string | number | boolean | string[]; - }; - }; + result: UiElicitationResponse; } -export interface SessionPermissionsHandlePendingPermissionRequestResult { +export interface PermissionRequestResult { /** * Whether the permission request was handled successfully */ success: boolean; } -export interface SessionPermissionsHandlePendingPermissionRequestParams { +export type PermissionDecision = + | { + /** + * The permission request was approved + */ + kind: "approved"; + } +| { + /** + * Denied because approval rules explicitly blocked it + */ + kind: "denied-by-rules"; + /** + * Rules that denied the request + */ + rules: unknown[]; + } + | { + /** + * Denied because no approval rule matched and user confirmation was unavailable + */ + kind: "denied-no-approval-rule-and-could-not-request-from-user"; + } + | { + /** + * Denied by the user during an interactive prompt + */ + kind: "denied-interactively-by-user"; + /** + * Optional feedback from the user explaining the denial + */ + feedback?: string; + } + | { + /** + * Denied by the organization's content exclusion policy + */ + kind: "denied-by-content-exclusion-policy"; + /** + * File path that triggered the exclusion + */ + path: string; + /** + * Human-readable explanation of why the path was excluded + */ + message: string; + } + | { + /** + * Denied by a permission request hook registered by an extension or plugin + */ + kind: "denied-by-permission-request-hook"; + /** + * Optional message from the hook explaining the denial + */ + message?: string; + /** + * Whether to interrupt the current agent turn + */ + interrupt?: boolean; + }; + +export interface PermissionDecisionRequest { /** * Target session identifier */ @@ -1283,77 +1332,21 @@ export interface SessionPermissionsHandlePendingPermissionRequestParams { * Request ID of the pending permission request */ requestId: string; - result: - | { - /** - * The permission request was approved - */ - kind: "approved"; - } - | { - /** - * Denied because approval rules explicitly blocked it - */ - kind: "denied-by-rules"; - /** - * Rules that denied the request - */ - rules: unknown[]; - } - | { - /** - * Denied because no approval rule matched and user confirmation was unavailable - */ - kind: "denied-no-approval-rule-and-could-not-request-from-user"; - } - | { - /** - * Denied by the user during an interactive prompt - */ - kind: "denied-interactively-by-user"; - /** - * Optional feedback from the user explaining the denial - */ - feedback?: string; - } - | { - /** - * Denied by the organization's content exclusion policy - */ - kind: "denied-by-content-exclusion-policy"; - /** - * File path that triggered the exclusion - */ - path: string; - /** - * Human-readable explanation of why the path was excluded - */ - message: string; - } - | { - /** - * Denied by a permission request hook registered by an extension or plugin - */ - kind: "denied-by-permission-request-hook"; - /** - * Optional message from the hook explaining the denial - */ - message?: string; - /** - * Whether to interrupt the current agent turn - */ - interrupt?: boolean; - }; + result: PermissionDecision; } -export interface SessionLogResult { +export interface LogResult { /** * The unique identifier of the emitted session event */ eventId: string; } -export interface SessionLogParams { +/** + * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". + */ +export type SessionLogLevel = "info" | "warning" | "error"; +export interface LogRequest { /** * Target session identifier */ @@ -1362,10 +1355,7 @@ export interface SessionLogParams { * Human-readable message */ message: string; - /** - * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". - */ - level?: "info" | "warning" | "error"; + level?: SessionLogLevel; /** * When true, the message is transient and not persisted to the session event log on disk */ @@ -1376,14 +1366,14 @@ export interface SessionLogParams { url?: string; } -export interface SessionShellExecResult { +export interface ShellExecResult { /** * Unique identifier for tracking streamed output */ processId: string; } -export interface SessionShellExecParams { +export interface ShellExecRequest { /** * Target session identifier */ @@ -1402,14 +1392,14 @@ export interface SessionShellExecParams { timeout?: number; } -export interface SessionShellKillResult { +export interface ShellKillResult { /** * Whether the signal was sent successfully */ killed: boolean; } -export interface SessionShellKillParams { +export interface ShellKillRequest { /** * Target session identifier */ @@ -1425,7 +1415,7 @@ export interface SessionShellKillParams { } /** @experimental */ -export interface SessionHistoryCompactResult { +export interface HistoryCompact { /** * Whether compaction completed successfully */ @@ -1470,7 +1460,7 @@ export interface SessionHistoryCompactResult { } /** @experimental */ -export interface SessionHistoryCompactParams { +export interface SessionHistoryCompactRequest { /** * Target session identifier */ @@ -1478,7 +1468,7 @@ export interface SessionHistoryCompactParams { } /** @experimental */ -export interface SessionHistoryTruncateResult { +export interface HistoryTruncateResult { /** * Number of events that were removed */ @@ -1486,7 +1476,7 @@ export interface SessionHistoryTruncateResult { } /** @experimental */ -export interface SessionHistoryTruncateParams { +export interface HistoryTruncateRequest { /** * Target session identifier */ @@ -1498,7 +1488,7 @@ export interface SessionHistoryTruncateParams { } /** @experimental */ -export interface SessionUsageGetMetricsResult { +export interface UsageMetrics { /** * Total user-initiated premium request cost across all models (may be fractional due to multipliers) */ @@ -1570,6 +1560,10 @@ export interface SessionUsageGetMetricsResult { * Total tokens written to prompt cache */ cacheWriteTokens: number; + /** + * Total output tokens used for reasoning + */ + reasoningTokens?: number; }; }; }; @@ -1588,7 +1582,7 @@ export interface SessionUsageGetMetricsResult { } /** @experimental */ -export interface SessionUsageGetMetricsParams { +export interface SessionUsageGetMetricsRequest { /** * Target session identifier */ @@ -1602,7 +1596,7 @@ export interface SessionFsReadFileResult { content: string; } -export interface SessionFsReadFileParams { +export interface SessionFsReadFileRequest { /** * Target session identifier */ @@ -1613,7 +1607,7 @@ export interface SessionFsReadFileParams { path: string; } -export interface SessionFsWriteFileParams { +export interface SessionFsWriteFileRequest { /** * Target session identifier */ @@ -1632,7 +1626,7 @@ export interface SessionFsWriteFileParams { mode?: number; } -export interface SessionFsAppendFileParams { +export interface SessionFsAppendFileRequest { /** * Target session identifier */ @@ -1658,7 +1652,7 @@ export interface SessionFsExistsResult { exists: boolean; } -export interface SessionFsExistsParams { +export interface SessionFsExistsRequest { /** * Target session identifier */ @@ -1692,7 +1686,7 @@ export interface SessionFsStatResult { birthtime: string; } -export interface SessionFsStatParams { +export interface SessionFsStatRequest { /** * Target session identifier */ @@ -1703,7 +1697,7 @@ export interface SessionFsStatParams { path: string; } -export interface SessionFsMkdirParams { +export interface SessionFsMkdirRequest { /** * Target session identifier */ @@ -1729,7 +1723,7 @@ export interface SessionFsReaddirResult { entries: string[]; } -export interface SessionFsReaddirParams { +export interface SessionFsReaddirRequest { /** * Target session identifier */ @@ -1756,7 +1750,7 @@ export interface SessionFsReaddirWithTypesResult { }[]; } -export interface SessionFsReaddirWithTypesParams { +export interface SessionFsReaddirWithTypesRequest { /** * Target session identifier */ @@ -1767,7 +1761,7 @@ export interface SessionFsReaddirWithTypesParams { path: string; } -export interface SessionFsRmParams { +export interface SessionFsRmRequest { /** * Target session identifier */ @@ -1786,7 +1780,7 @@ export interface SessionFsRmParams { force?: boolean; } -export interface SessionFsRenameParams { +export interface SessionFsRenameRequest { /** * Target session identifier */ @@ -1804,41 +1798,41 @@ export interface SessionFsRenameParams { /** Create typed server-scoped RPC methods (no session required). */ export function createServerRpc(connection: MessageConnection) { return { - ping: async (params: PingParams): Promise => + ping: async (params: PingRequest): Promise => connection.sendRequest("ping", params), models: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("models.list", {}), }, tools: { - list: async (params: ToolsListParams): Promise => + list: async (params: ToolsListRequest): Promise => connection.sendRequest("tools.list", params), }, account: { - getQuota: async (): Promise => + getQuota: async (): Promise => connection.sendRequest("account.getQuota", {}), }, mcp: { config: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("mcp.config.list", {}), - add: async (params: McpConfigAddParams): Promise => + add: async (params: McpConfigAddRequest): Promise => connection.sendRequest("mcp.config.add", params), - update: async (params: McpConfigUpdateParams): Promise => + update: async (params: McpConfigUpdateRequest): Promise => connection.sendRequest("mcp.config.update", params), - remove: async (params: McpConfigRemoveParams): Promise => + remove: async (params: McpConfigRemoveRequest): Promise => connection.sendRequest("mcp.config.remove", params), }, - discover: async (params: McpDiscoverParams): Promise => + discover: async (params: McpDiscoverRequest): Promise => connection.sendRequest("mcp.discover", params), }, sessionFs: { - setProvider: async (params: SessionFsSetProviderParams): Promise => + setProvider: async (params: SessionFsSetProviderRequest): Promise => connection.sendRequest("sessionFs.setProvider", params), }, /** @experimental */ sessions: { - fork: async (params: SessionsForkParams): Promise => + fork: async (params: SessionsForkRequest): Promise => connection.sendRequest("sessions.fork", params), }, }; @@ -1848,125 +1842,125 @@ export function createServerRpc(connection: MessageConnection) { export function createSessionRpc(connection: MessageConnection, sessionId: string) { return { model: { - getCurrent: async (): Promise => + getCurrent: async (): Promise => connection.sendRequest("session.model.getCurrent", { sessionId }), - switchTo: async (params: Omit): Promise => + switchTo: async (params: Omit): Promise => connection.sendRequest("session.model.switchTo", { sessionId, ...params }), }, mode: { - get: async (): Promise => + get: async (): Promise => connection.sendRequest("session.mode.get", { sessionId }), - set: async (params: Omit): Promise => + set: async (params: Omit): Promise => connection.sendRequest("session.mode.set", { sessionId, ...params }), }, plan: { - read: async (): Promise => + read: async (): Promise => connection.sendRequest("session.plan.read", { sessionId }), - update: async (params: Omit): Promise => + update: async (params: Omit): Promise => connection.sendRequest("session.plan.update", { sessionId, ...params }), - delete: async (): Promise => + delete: async (): Promise => connection.sendRequest("session.plan.delete", { sessionId }), }, workspace: { - listFiles: async (): Promise => + listFiles: async (): Promise => connection.sendRequest("session.workspace.listFiles", { sessionId }), - readFile: async (params: Omit): Promise => + readFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }), - createFile: async (params: Omit): Promise => + createFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.createFile", { sessionId, ...params }), }, /** @experimental */ fleet: { - start: async (params: Omit): Promise => + start: async (params: Omit): Promise => connection.sendRequest("session.fleet.start", { sessionId, ...params }), }, /** @experimental */ agent: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.agent.list", { sessionId }), - getCurrent: async (): Promise => + getCurrent: async (): Promise => connection.sendRequest("session.agent.getCurrent", { sessionId }), - select: async (params: Omit): Promise => + select: async (params: Omit): Promise => connection.sendRequest("session.agent.select", { sessionId, ...params }), - deselect: async (): Promise => + deselect: async (): Promise => connection.sendRequest("session.agent.deselect", { sessionId }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.agent.reload", { sessionId }), }, /** @experimental */ skills: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.skills.list", { sessionId }), - enable: async (params: Omit): Promise => + enable: async (params: Omit): Promise => connection.sendRequest("session.skills.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + disable: async (params: Omit): Promise => connection.sendRequest("session.skills.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.skills.reload", { sessionId }), }, /** @experimental */ mcp: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.mcp.list", { sessionId }), - enable: async (params: Omit): Promise => + enable: async (params: Omit): Promise => connection.sendRequest("session.mcp.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + disable: async (params: Omit): Promise => connection.sendRequest("session.mcp.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.mcp.reload", { sessionId }), }, /** @experimental */ plugins: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.plugins.list", { sessionId }), }, /** @experimental */ extensions: { - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.extensions.list", { sessionId }), - enable: async (params: Omit): Promise => + enable: async (params: Omit): Promise => connection.sendRequest("session.extensions.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + disable: async (params: Omit): Promise => connection.sendRequest("session.extensions.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.extensions.reload", { sessionId }), }, tools: { - handlePendingToolCall: async (params: Omit): Promise => + handlePendingToolCall: async (params: Omit): Promise => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params }), }, commands: { - handlePendingCommand: async (params: Omit): Promise => + handlePendingCommand: async (params: Omit): Promise => connection.sendRequest("session.commands.handlePendingCommand", { sessionId, ...params }), }, ui: { - elicitation: async (params: Omit): Promise => + elicitation: async (params: Omit): Promise => connection.sendRequest("session.ui.elicitation", { sessionId, ...params }), - handlePendingElicitation: async (params: Omit): Promise => + handlePendingElicitation: async (params: Omit): Promise => connection.sendRequest("session.ui.handlePendingElicitation", { sessionId, ...params }), }, permissions: { - handlePendingPermissionRequest: async (params: Omit): Promise => + handlePendingPermissionRequest: async (params: Omit): Promise => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params }), }, - log: async (params: Omit): Promise => + log: async (params: Omit): Promise => connection.sendRequest("session.log", { sessionId, ...params }), shell: { - exec: async (params: Omit): Promise => + exec: async (params: Omit): Promise => connection.sendRequest("session.shell.exec", { sessionId, ...params }), - kill: async (params: Omit): Promise => + kill: async (params: Omit): Promise => connection.sendRequest("session.shell.kill", { sessionId, ...params }), }, /** @experimental */ history: { - compact: async (): Promise => + compact: async (): Promise => connection.sendRequest("session.history.compact", { sessionId }), - truncate: async (params: Omit): Promise => + truncate: async (params: Omit): Promise => connection.sendRequest("session.history.truncate", { sessionId, ...params }), }, /** @experimental */ usage: { - getMetrics: async (): Promise => + getMetrics: async (): Promise => connection.sendRequest("session.usage.getMetrics", { sessionId }), }, }; @@ -1974,16 +1968,16 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin /** Handler for `sessionFs` client session API methods. */ export interface SessionFsHandler { - readFile(params: SessionFsReadFileParams): Promise; - writeFile(params: SessionFsWriteFileParams): Promise; - appendFile(params: SessionFsAppendFileParams): Promise; - exists(params: SessionFsExistsParams): Promise; - stat(params: SessionFsStatParams): Promise; - mkdir(params: SessionFsMkdirParams): Promise; - readdir(params: SessionFsReaddirParams): Promise; - readdirWithTypes(params: SessionFsReaddirWithTypesParams): Promise; - rm(params: SessionFsRmParams): Promise; - rename(params: SessionFsRenameParams): Promise; + readFile(params: SessionFsReadFileRequest): Promise; + writeFile(params: SessionFsWriteFileRequest): Promise; + appendFile(params: SessionFsAppendFileRequest): Promise; + exists(params: SessionFsExistsRequest): Promise; + stat(params: SessionFsStatRequest): Promise; + mkdir(params: SessionFsMkdirRequest): Promise; + readdir(params: SessionFsReaddirRequest): Promise; + readdirWithTypes(params: SessionFsReaddirWithTypesRequest): Promise; + rm(params: SessionFsRmRequest): Promise; + rename(params: SessionFsRenameRequest): Promise; } /** All client session API handler groups. */ @@ -2001,52 +1995,52 @@ export function registerClientSessionApiHandlers( connection: MessageConnection, getHandlers: (sessionId: string) => ClientSessionApiHandlers, ): void { - connection.onRequest("sessionFs.readFile", async (params: SessionFsReadFileParams) => { + connection.onRequest("sessionFs.readFile", async (params: SessionFsReadFileRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.readFile(params); }); - connection.onRequest("sessionFs.writeFile", async (params: SessionFsWriteFileParams) => { + connection.onRequest("sessionFs.writeFile", async (params: SessionFsWriteFileRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.writeFile(params); }); - connection.onRequest("sessionFs.appendFile", async (params: SessionFsAppendFileParams) => { + connection.onRequest("sessionFs.appendFile", async (params: SessionFsAppendFileRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.appendFile(params); }); - connection.onRequest("sessionFs.exists", async (params: SessionFsExistsParams) => { + connection.onRequest("sessionFs.exists", async (params: SessionFsExistsRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.exists(params); }); - connection.onRequest("sessionFs.stat", async (params: SessionFsStatParams) => { + connection.onRequest("sessionFs.stat", async (params: SessionFsStatRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.stat(params); }); - connection.onRequest("sessionFs.mkdir", async (params: SessionFsMkdirParams) => { + connection.onRequest("sessionFs.mkdir", async (params: SessionFsMkdirRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.mkdir(params); }); - connection.onRequest("sessionFs.readdir", async (params: SessionFsReaddirParams) => { + connection.onRequest("sessionFs.readdir", async (params: SessionFsReaddirRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.readdir(params); }); - connection.onRequest("sessionFs.readdirWithTypes", async (params: SessionFsReaddirWithTypesParams) => { + connection.onRequest("sessionFs.readdirWithTypes", async (params: SessionFsReaddirWithTypesRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.readdirWithTypes(params); }); - connection.onRequest("sessionFs.rm", async (params: SessionFsRmParams) => { + connection.onRequest("sessionFs.rm", async (params: SessionFsRmRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.rm(params); }); - connection.onRequest("sessionFs.rename", async (params: SessionFsRenameParams) => { + connection.onRequest("sessionFs.rename", async (params: SessionFsRenameRequest) => { const handler = getHandlers(params.sessionId).sessionFs; if (!handler) throw new Error(`No sessionFs handler registered for session: ${params.sessionId}`); return handler.rename(params); diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts index 7cfc60522..2a5b08b21 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -297,12 +297,7 @@ export type SessionEvent = /** * Session title change payload containing the new display title */ - data: { - /** - * The new display title for the session - */ - title: string; - }; + data: {}; } | { /** @@ -755,6 +750,10 @@ export type SessionEvent = * Total tokens written to prompt cache across all requests */ cacheWriteTokens: number; + /** + * Total reasoning tokens produced across all requests to this model + */ + reasoningTokens?: number; }; }; }; @@ -1176,10 +1175,6 @@ export type SessionEvent = * Issue, pull request, or discussion number */ number: number; - /** - * Title of the referenced item - */ - title: string; /** * Type of GitHub reference */ @@ -1588,6 +1583,10 @@ export type SessionEvent = * Number of tokens written to prompt cache */ cacheWriteTokens?: number; + /** + * Number of output tokens used for reasoning (e.g., chain-of-thought) + */ + reasoningTokens?: number; /** * Model multiplier cost for billing purposes */ @@ -2009,10 +2008,6 @@ export type SessionEvent = * Resource name identifier */ name: string; - /** - * Human-readable display title for the resource - */ - title?: string; /** * URI identifying the resource */ @@ -2042,35 +2037,7 @@ export type SessionEvent = /** * The embedded resource contents, either text or base64-encoded binary */ - resource: - | { - /** - * URI identifying the resource - */ - uri: string; - /** - * MIME type of the text content - */ - mimeType?: string; - /** - * Text content of the resource - */ - text: string; - } - | { - /** - * URI identifying the resource - */ - uri: string; - /** - * MIME type of the blob content - */ - mimeType?: string; - /** - * Base64-encoded binary content of the resource - */ - blob: string; - }; + resource: EmbeddedTextResourceContents | EmbeddedBlobResourceContents; } )[]; }; @@ -3764,3 +3731,32 @@ export type SessionEvent = }[]; }; }; + +export interface EmbeddedTextResourceContents { + /** + * URI identifying the resource + */ + uri: string; + /** + * MIME type of the text content + */ + mimeType?: string; + /** + * Text content of the resource + */ + text: string; +} +export interface EmbeddedBlobResourceContents { + /** + * URI identifying the resource + */ + uri: string; + /** + * MIME type of the blob content + */ + mimeType?: string; + /** + * Base64-encoded binary content of the resource + */ + blob: string; +} diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts index cb8dd7ad2..1318b3df4 100644 --- a/nodejs/src/types.ts +++ b/nodejs/src/types.ts @@ -744,11 +744,9 @@ export interface PermissionRequest { [key: string]: unknown; } -import type { SessionPermissionsHandlePendingPermissionRequestParams } from "./generated/rpc.js"; +import type { PermissionDecisionRequest } from "./generated/rpc.js"; -export type PermissionRequestResult = - | SessionPermissionsHandlePendingPermissionRequestParams["result"] - | { kind: "no-result" }; +export type PermissionRequestResult = PermissionDecisionRequest["result"] | { kind: "no-result" }; export type PermissionHandler = ( request: PermissionRequest, diff --git a/nodejs/test/e2e/rpc.test.ts b/nodejs/test/e2e/rpc.test.ts index d4d732efd..173d6c032 100644 --- a/nodejs/test/e2e/rpc.test.ts +++ b/nodejs/test/e2e/rpc.test.ts @@ -109,19 +109,19 @@ describe("Session RPC", async () => { // Get initial mode (default should be interactive) const initial = await session.rpc.mode.get(); - expect(initial.mode).toBe("interactive"); + expect(initial).toBe("interactive"); // Switch to plan mode const planResult = await session.rpc.mode.set({ mode: "plan" }); - expect(planResult.mode).toBe("plan"); + expect(planResult).toBe("plan"); // Verify mode persisted const afterPlan = await session.rpc.mode.get(); - expect(afterPlan.mode).toBe("plan"); + expect(afterPlan).toBe("plan"); // Switch back to interactive const interactiveResult = await session.rpc.mode.set({ mode: "interactive" }); - expect(interactiveResult.mode).toBe("interactive"); + expect(interactiveResult).toBe("interactive"); }); it("should read, update, and delete plan", async () => { diff --git a/python/copilot/client.py b/python/copilot/client.py index d260dcc91..17071e502 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -762,23 +762,24 @@ def _get_bundled_cli_path() -> str | None: def _extract_transform_callbacks( - system_message: dict | None, -) -> tuple[dict | None, dict[str, SectionTransformFn] | None]: + system_message: SystemMessageConfig | dict[str, Any] | None, +) -> tuple[dict[str, Any] | None, dict[str, SectionTransformFn] | None]: """Extract function-valued actions from system message config. Returns a wire-safe payload (with callable actions replaced by ``"transform"``) and a dict of transform callbacks keyed by section ID. """ + wire_system_message = cast(dict[str, Any] | None, system_message) if ( - not system_message - or system_message.get("mode") != "customize" - or not system_message.get("sections") + not wire_system_message + or wire_system_message.get("mode") != "customize" + or not wire_system_message.get("sections") ): - return system_message, None + return wire_system_message, None callbacks: dict[str, SectionTransformFn] = {} - wire_sections: dict[str, dict] = {} - for section_id, override in system_message["sections"].items(): + wire_sections: dict[str, Any] = {} + for section_id, override in wire_system_message["sections"].items(): if not override: continue action = override.get("action") @@ -789,9 +790,9 @@ def _extract_transform_callbacks( wire_sections[section_id] = override if not callbacks: - return system_message, None + return wire_system_message, None - wire_payload = {**system_message, "sections": wire_sections} + wire_payload = {**wire_system_message, "sections": wire_sections} return wire_payload, callbacks @@ -1798,9 +1799,9 @@ async def list_models(self) -> list[ModelInfo]: # Use custom handler instead of CLI RPC result = self._on_list_models() if inspect.isawaitable(result): - models = await result + models = cast(list[ModelInfo], await result) else: - models = result + models = cast(list[ModelInfo], result) else: if not self._client: raise RuntimeError("Client not connected") diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 19265c557..41041708c 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -15,34 +15,26 @@ from dataclasses import dataclass from typing import Any, TypeVar, Callable, cast +from datetime import datetime from enum import Enum from uuid import UUID - +import dateutil.parser T = TypeVar("T") EnumT = TypeVar("EnumT", bound=Enum) - def from_str(x: Any) -> str: assert isinstance(x, str) return x - -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_int(x: Any) -> int: + assert isinstance(x, int) and not isinstance(x, bool) return x - def from_none(x: Any) -> Any: assert x is None return x - def from_union(fs, x): for f in fs: try: @@ -51,74 +43,73 @@ def from_union(fs, x): pass assert False +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 from_list(f: Callable[[Any], T], x: Any) -> list[T]: assert isinstance(x, list) return [f(y) for y in x] - def to_class(c: type[T], x: Any) -> dict: assert isinstance(x, c) return cast(Any, x).to_dict() - def from_bool(x: Any) -> bool: assert isinstance(x, bool) return x - def from_dict(f: Callable[[Any], T], x: Any) -> dict[str, T]: assert isinstance(x, dict) return { k: f(v) for (k, v) in x.items() } +def from_datetime(x: Any) -> datetime: + return dateutil.parser.parse(x) def to_enum(c: type[EnumT], x: Any) -> EnumT: assert isinstance(x, c) return x.value - -def from_int(x: Any) -> int: - assert isinstance(x, int) and not isinstance(x, bool) - return x - - @dataclass class PingResult: message: str """Echoed message (or default greeting)""" - protocol_version: float + protocol_version: int """Server protocol version number""" - timestamp: float + timestamp: int """Server timestamp in milliseconds""" @staticmethod def from_dict(obj: Any) -> 'PingResult': assert isinstance(obj, dict) message = from_str(obj.get("message")) - protocol_version = from_float(obj.get("protocolVersion")) - timestamp = from_float(obj.get("timestamp")) + protocol_version = from_int(obj.get("protocolVersion")) + timestamp = from_int(obj.get("timestamp")) return PingResult(message, protocol_version, timestamp) def to_dict(self) -> dict: result: dict = {} result["message"] = from_str(self.message) - result["protocolVersion"] = to_float(self.protocol_version) - result["timestamp"] = to_float(self.timestamp) + result["protocolVersion"] = from_int(self.protocol_version) + result["timestamp"] = from_int(self.timestamp) return result - @dataclass -class PingParams: +class PingRequest: message: str | None = None """Optional message to echo back""" @staticmethod - def from_dict(obj: Any) -> 'PingParams': + def from_dict(obj: Any) -> 'PingRequest': assert isinstance(obj, dict) message = from_union([from_str, from_none], obj.get("message")) - return PingParams(message) + return PingRequest(message) def to_dict(self) -> dict: result: dict = {} @@ -126,34 +117,32 @@ def to_dict(self) -> dict: result["message"] = from_union([from_str, from_none], self.message) return result - @dataclass -class Billing: +class ModelBilling: """Billing information""" multiplier: float """Billing cost multiplier relative to the base rate""" @staticmethod - def from_dict(obj: Any) -> 'Billing': + def from_dict(obj: Any) -> 'ModelBilling': assert isinstance(obj, dict) multiplier = from_float(obj.get("multiplier")) - return Billing(multiplier) + return ModelBilling(multiplier) def to_dict(self) -> dict: result: dict = {} result["multiplier"] = to_float(self.multiplier) return result - @dataclass class ModelCapabilitiesLimitsVision: """Vision-specific limits""" - max_prompt_image_size: float + max_prompt_image_size: int """Maximum image size in bytes""" - max_prompt_images: float + max_prompt_images: int """Maximum number of images per prompt""" supported_media_types: list[str] @@ -162,56 +151,53 @@ class ModelCapabilitiesLimitsVision: @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesLimitsVision': assert isinstance(obj, dict) - max_prompt_image_size = from_float(obj.get("max_prompt_image_size")) - max_prompt_images = from_float(obj.get("max_prompt_images")) + max_prompt_image_size = from_int(obj.get("max_prompt_image_size")) + max_prompt_images = from_int(obj.get("max_prompt_images")) supported_media_types = from_list(from_str, obj.get("supported_media_types")) return ModelCapabilitiesLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types) def to_dict(self) -> dict: result: dict = {} - result["max_prompt_image_size"] = to_float(self.max_prompt_image_size) - result["max_prompt_images"] = to_float(self.max_prompt_images) + result["max_prompt_image_size"] = from_int(self.max_prompt_image_size) + result["max_prompt_images"] = from_int(self.max_prompt_images) result["supported_media_types"] = from_list(from_str, self.supported_media_types) return result - @dataclass class ModelCapabilitiesLimits: """Token limits for prompts, outputs, and context window""" - max_context_window_tokens: float + max_context_window_tokens: int """Maximum total context window size in tokens""" - max_output_tokens: float | None = None + max_output_tokens: int | None = None """Maximum number of output/completion tokens""" - max_prompt_tokens: float | None = None + max_prompt_tokens: int | None = None """Maximum number of prompt/input tokens""" vision: ModelCapabilitiesLimitsVision | None = None - """Vision-specific limits""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesLimits': assert isinstance(obj, dict) - max_context_window_tokens = from_float(obj.get("max_context_window_tokens")) - max_output_tokens = from_union([from_float, from_none], obj.get("max_output_tokens")) - max_prompt_tokens = from_union([from_float, from_none], obj.get("max_prompt_tokens")) + max_context_window_tokens = from_int(obj.get("max_context_window_tokens")) + max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) + max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) vision = from_union([ModelCapabilitiesLimitsVision.from_dict, from_none], obj.get("vision")) return ModelCapabilitiesLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) def to_dict(self) -> dict: result: dict = {} - result["max_context_window_tokens"] = to_float(self.max_context_window_tokens) + result["max_context_window_tokens"] = from_int(self.max_context_window_tokens) if self.max_output_tokens is not None: - result["max_output_tokens"] = from_union([to_float, from_none], self.max_output_tokens) + result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) if self.max_prompt_tokens is not None: - result["max_prompt_tokens"] = from_union([to_float, from_none], self.max_prompt_tokens) + result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) if self.vision is not None: result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesLimitsVision, x), from_none], self.vision) return result - @dataclass class ModelCapabilitiesSupports: """Feature flags indicating what the model supports""" @@ -237,16 +223,12 @@ def to_dict(self) -> dict: result["vision"] = from_union([from_bool, from_none], self.vision) return result - @dataclass class ModelCapabilities: """Model capabilities and limits""" limits: ModelCapabilitiesLimits - """Token limits for prompts, outputs, and context window""" - supports: ModelCapabilitiesSupports - """Feature flags indicating what the model supports""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilities': @@ -261,9 +243,8 @@ def to_dict(self) -> dict: result["supports"] = to_class(ModelCapabilitiesSupports, self.supports) return result - @dataclass -class Policy: +class ModelPolicy: """Policy state (if applicable)""" state: str @@ -273,11 +254,11 @@ class Policy: """Usage terms or conditions for this model""" @staticmethod - def from_dict(obj: Any) -> 'Policy': + def from_dict(obj: Any) -> 'ModelPolicy': assert isinstance(obj, dict) state = from_str(obj.get("state")) terms = from_str(obj.get("terms")) - return Policy(state, terms) + return ModelPolicy(state, terms) def to_dict(self) -> dict: result: dict = {} @@ -285,27 +266,20 @@ def to_dict(self) -> dict: result["terms"] = from_str(self.terms) return result - @dataclass class Model: capabilities: ModelCapabilities - """Model capabilities and limits""" - id: str """Model identifier (e.g., "claude-sonnet-4.5")""" name: str """Display name""" - billing: Billing | None = None - """Billing information""" - + billing: ModelBilling | None = None default_reasoning_effort: str | None = None """Default reasoning effort level (only present if model supports reasoning effort)""" - policy: Policy | None = None - """Policy state (if applicable)""" - + policy: ModelPolicy | None = None supported_reasoning_efforts: list[str] | None = None """Supported reasoning effort levels (only present if model supports reasoning effort)""" @@ -315,9 +289,9 @@ def from_dict(obj: Any) -> 'Model': capabilities = ModelCapabilities.from_dict(obj.get("capabilities")) id = from_str(obj.get("id")) name = from_str(obj.get("name")) - billing = from_union([Billing.from_dict, from_none], obj.get("billing")) + billing = from_union([ModelBilling.from_dict, from_none], obj.get("billing")) default_reasoning_effort = from_union([from_str, from_none], obj.get("defaultReasoningEffort")) - policy = from_union([Policy.from_dict, from_none], obj.get("policy")) + policy = from_union([ModelPolicy.from_dict, from_none], obj.get("policy")) supported_reasoning_efforts = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supportedReasoningEfforts")) return Model(capabilities, id, name, billing, default_reasoning_effort, policy, supported_reasoning_efforts) @@ -327,33 +301,31 @@ def to_dict(self) -> dict: result["id"] = from_str(self.id) result["name"] = from_str(self.name) if self.billing is not None: - result["billing"] = from_union([lambda x: to_class(Billing, x), from_none], self.billing) + result["billing"] = from_union([lambda x: to_class(ModelBilling, x), from_none], self.billing) if self.default_reasoning_effort is not None: result["defaultReasoningEffort"] = from_union([from_str, from_none], self.default_reasoning_effort) if self.policy is not None: - result["policy"] = from_union([lambda x: to_class(Policy, x), from_none], self.policy) + result["policy"] = from_union([lambda x: to_class(ModelPolicy, x), from_none], self.policy) if self.supported_reasoning_efforts is not None: result["supportedReasoningEfforts"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_reasoning_efforts) return result - @dataclass -class ModelsListResult: +class ModelList: models: list[Model] """List of available models with full metadata""" @staticmethod - def from_dict(obj: Any) -> 'ModelsListResult': + def from_dict(obj: Any) -> 'ModelList': assert isinstance(obj, dict) models = from_list(Model.from_dict, obj.get("models")) - return ModelsListResult(models) + return ModelList(models) def to_dict(self) -> dict: result: dict = {} result["models"] = from_list(lambda x: to_class(Model, x), self.models) return result - @dataclass class Tool: description: str @@ -394,36 +366,34 @@ def to_dict(self) -> dict: result["parameters"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.parameters) return result - @dataclass -class ToolsListResult: +class ToolList: tools: list[Tool] """List of available built-in tools with metadata""" @staticmethod - def from_dict(obj: Any) -> 'ToolsListResult': + def from_dict(obj: Any) -> 'ToolList': assert isinstance(obj, dict) tools = from_list(Tool.from_dict, obj.get("tools")) - return ToolsListResult(tools) + return ToolList(tools) def to_dict(self) -> dict: result: dict = {} result["tools"] = from_list(lambda x: to_class(Tool, x), self.tools) return result - @dataclass -class ToolsListParams: +class ToolsListRequest: model: str | None = None """Optional model ID — when provided, the returned tool list reflects model-specific overrides """ @staticmethod - def from_dict(obj: Any) -> 'ToolsListParams': + def from_dict(obj: Any) -> 'ToolsListRequest': assert isinstance(obj, dict) model = from_union([from_str, from_none], obj.get("model")) - return ToolsListParams(model) + return ToolsListRequest(model) def to_dict(self) -> dict: result: dict = {} @@ -431,13 +401,12 @@ def to_dict(self) -> dict: result["model"] = from_union([from_str, from_none], self.model) return result - @dataclass -class QuotaSnapshot: - entitlement_requests: float +class AccountQuotaSnapshot: + entitlement_requests: int """Number of requests included in the entitlement""" - overage: float + overage: int """Number of overage requests made this period""" overage_allowed_with_exhausted_quota: bool @@ -446,102 +415,100 @@ class QuotaSnapshot: remaining_percentage: float """Percentage of entitlement remaining""" - used_requests: float + used_requests: int """Number of requests used so far this period""" - reset_date: str | None = None + reset_date: datetime | None = None """Date when the quota resets (ISO 8601)""" @staticmethod - def from_dict(obj: Any) -> 'QuotaSnapshot': + def from_dict(obj: Any) -> 'AccountQuotaSnapshot': assert isinstance(obj, dict) - entitlement_requests = from_float(obj.get("entitlementRequests")) - overage = from_float(obj.get("overage")) + entitlement_requests = from_int(obj.get("entitlementRequests")) + overage = from_int(obj.get("overage")) overage_allowed_with_exhausted_quota = from_bool(obj.get("overageAllowedWithExhaustedQuota")) remaining_percentage = from_float(obj.get("remainingPercentage")) - used_requests = from_float(obj.get("usedRequests")) - reset_date = from_union([from_str, from_none], obj.get("resetDate")) - return QuotaSnapshot(entitlement_requests, overage, overage_allowed_with_exhausted_quota, remaining_percentage, used_requests, reset_date) + used_requests = from_int(obj.get("usedRequests")) + reset_date = from_union([from_datetime, from_none], obj.get("resetDate")) + return AccountQuotaSnapshot(entitlement_requests, overage, overage_allowed_with_exhausted_quota, remaining_percentage, used_requests, reset_date) def to_dict(self) -> dict: result: dict = {} - result["entitlementRequests"] = to_float(self.entitlement_requests) - result["overage"] = to_float(self.overage) + result["entitlementRequests"] = from_int(self.entitlement_requests) + result["overage"] = from_int(self.overage) result["overageAllowedWithExhaustedQuota"] = from_bool(self.overage_allowed_with_exhausted_quota) result["remainingPercentage"] = to_float(self.remaining_percentage) - result["usedRequests"] = to_float(self.used_requests) + result["usedRequests"] = from_int(self.used_requests) if self.reset_date is not None: - result["resetDate"] = from_union([from_str, from_none], self.reset_date) + result["resetDate"] = from_union([lambda x: x.isoformat(), from_none], self.reset_date) return result - @dataclass -class AccountGetQuotaResult: - quota_snapshots: dict[str, QuotaSnapshot] +class AccountQuota: + quota_snapshots: dict[str, AccountQuotaSnapshot] """Quota snapshots keyed by type (e.g., chat, completions, premium_interactions)""" @staticmethod - def from_dict(obj: Any) -> 'AccountGetQuotaResult': + def from_dict(obj: Any) -> 'AccountQuota': assert isinstance(obj, dict) - quota_snapshots = from_dict(QuotaSnapshot.from_dict, obj.get("quotaSnapshots")) - return AccountGetQuotaResult(quota_snapshots) + quota_snapshots = from_dict(AccountQuotaSnapshot.from_dict, obj.get("quotaSnapshots")) + return AccountQuota(quota_snapshots) def to_dict(self) -> dict: result: dict = {} - result["quotaSnapshots"] = from_dict(lambda x: to_class(QuotaSnapshot, x), self.quota_snapshots) + result["quotaSnapshots"] = from_dict(lambda x: to_class(AccountQuotaSnapshot, x), self.quota_snapshots) return result - -class FilterMappingEnum(Enum): +class MCPConfigFilterMappingString(Enum): HIDDEN_CHARACTERS = "hidden_characters" MARKDOWN = "markdown" NONE = "none" - -class ServerType(Enum): +class MCPConfigType(Enum): HTTP = "http" LOCAL = "local" SSE = "sse" STDIO = "stdio" - @dataclass -class ServerValue: +class MCPConfigServer: """MCP server configuration (local/stdio or remote/http)""" args: list[str] | None = None command: str | None = None cwd: str | None = None env: dict[str, str] | None = None - filter_mapping: dict[str, FilterMappingEnum] | FilterMappingEnum | None = None + filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None is_default_server: bool | None = None - timeout: float | None = None + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + tools: list[str] | None = None """Tools to include. Defaults to all tools if not specified.""" - type: ServerType | None = None + type: MCPConfigType | None = None headers: dict[str, str] | None = None oauth_client_id: str | None = None oauth_public_client: bool | None = None url: str | None = None @staticmethod - def from_dict(obj: Any) -> 'ServerValue': + def from_dict(obj: Any) -> 'MCPConfigServer': assert isinstance(obj, dict) args = from_union([lambda x: from_list(from_str, x), from_none], obj.get("args")) command = from_union([from_str, from_none], obj.get("command")) cwd = from_union([from_str, from_none], obj.get("cwd")) env = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("env")) - filter_mapping = from_union([lambda x: from_dict(FilterMappingEnum, x), FilterMappingEnum, from_none], obj.get("filterMapping")) + filter_mapping = from_union([lambda x: from_dict(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, from_none], obj.get("filterMapping")) is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - timeout = from_union([from_float, from_none], obj.get("timeout")) + timeout = from_union([from_int, from_none], obj.get("timeout")) tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - type = from_union([ServerType, from_none], obj.get("type")) + type = from_union([MCPConfigType, from_none], obj.get("type")) headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers")) oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId")) oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) url = from_union([from_str, from_none], obj.get("url")) - return ServerValue(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) + return MCPConfigServer(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) def to_dict(self) -> dict: result: dict = {} @@ -554,15 +521,15 @@ def to_dict(self) -> dict: if self.env is not None: result["env"] = from_union([lambda x: from_dict(from_str, x), from_none], self.env) if self.filter_mapping is not None: - result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(FilterMappingEnum, x), x), lambda x: to_enum(FilterMappingEnum, x), from_none], self.filter_mapping) + result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping) if self.is_default_server is not None: result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) if self.timeout is not None: - result["timeout"] = from_union([to_float, from_none], self.timeout) + result["timeout"] = from_union([from_int, from_none], self.timeout) if self.tools is not None: result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) if self.type is not None: - result["type"] = from_union([lambda x: to_enum(ServerType, x), from_none], self.type) + result["type"] = from_union([lambda x: to_enum(MCPConfigType, x), from_none], self.type) if self.headers is not None: result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers) if self.oauth_client_id is not None: @@ -573,61 +540,61 @@ def to_dict(self) -> dict: result["url"] = from_union([from_str, from_none], self.url) return result - @dataclass -class MCPConfigListResult: - servers: dict[str, ServerValue] +class MCPConfigList: + servers: dict[str, MCPConfigServer] """All MCP servers from user config, keyed by name""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigListResult': + def from_dict(obj: Any) -> 'MCPConfigList': assert isinstance(obj, dict) - servers = from_dict(ServerValue.from_dict, obj.get("servers")) - return MCPConfigListResult(servers) + servers = from_dict(MCPConfigServer.from_dict, obj.get("servers")) + return MCPConfigList(servers) def to_dict(self) -> dict: result: dict = {} - result["servers"] = from_dict(lambda x: to_class(ServerValue, x), self.servers) + result["servers"] = from_dict(lambda x: to_class(MCPConfigServer, x), self.servers) return result - @dataclass -class MCPConfigAddParamsConfig: +class MCPConfigAddConfig: """MCP server configuration (local/stdio or remote/http)""" args: list[str] | None = None command: str | None = None cwd: str | None = None env: dict[str, str] | None = None - filter_mapping: dict[str, FilterMappingEnum] | FilterMappingEnum | None = None + filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None is_default_server: bool | None = None - timeout: float | None = None + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + tools: list[str] | None = None """Tools to include. Defaults to all tools if not specified.""" - type: ServerType | None = None + type: MCPConfigType | None = None headers: dict[str, str] | None = None oauth_client_id: str | None = None oauth_public_client: bool | None = None url: str | None = None @staticmethod - def from_dict(obj: Any) -> 'MCPConfigAddParamsConfig': + def from_dict(obj: Any) -> 'MCPConfigAddConfig': assert isinstance(obj, dict) args = from_union([lambda x: from_list(from_str, x), from_none], obj.get("args")) command = from_union([from_str, from_none], obj.get("command")) cwd = from_union([from_str, from_none], obj.get("cwd")) env = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("env")) - filter_mapping = from_union([lambda x: from_dict(FilterMappingEnum, x), FilterMappingEnum, from_none], obj.get("filterMapping")) + filter_mapping = from_union([lambda x: from_dict(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, from_none], obj.get("filterMapping")) is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - timeout = from_union([from_float, from_none], obj.get("timeout")) + timeout = from_union([from_int, from_none], obj.get("timeout")) tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - type = from_union([ServerType, from_none], obj.get("type")) + type = from_union([MCPConfigType, from_none], obj.get("type")) headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers")) oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId")) oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) url = from_union([from_str, from_none], obj.get("url")) - return MCPConfigAddParamsConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) + return MCPConfigAddConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) def to_dict(self) -> dict: result: dict = {} @@ -640,15 +607,15 @@ def to_dict(self) -> dict: if self.env is not None: result["env"] = from_union([lambda x: from_dict(from_str, x), from_none], self.env) if self.filter_mapping is not None: - result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(FilterMappingEnum, x), x), lambda x: to_enum(FilterMappingEnum, x), from_none], self.filter_mapping) + result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping) if self.is_default_server is not None: result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) if self.timeout is not None: - result["timeout"] = from_union([to_float, from_none], self.timeout) + result["timeout"] = from_union([from_int, from_none], self.timeout) if self.tools is not None: result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) if self.type is not None: - result["type"] = from_union([lambda x: to_enum(ServerType, x), from_none], self.type) + result["type"] = from_union([lambda x: to_enum(MCPConfigType, x), from_none], self.type) if self.headers is not None: result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers) if self.oauth_client_id is not None: @@ -659,66 +626,64 @@ def to_dict(self) -> dict: result["url"] = from_union([from_str, from_none], self.url) return result - @dataclass -class MCPConfigAddParams: - config: MCPConfigAddParamsConfig - """MCP server configuration (local/stdio or remote/http)""" - +class MCPConfigAddRequest: + config: MCPConfigAddConfig name: str """Unique name for the MCP server""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigAddParams': + def from_dict(obj: Any) -> 'MCPConfigAddRequest': assert isinstance(obj, dict) - config = MCPConfigAddParamsConfig.from_dict(obj.get("config")) + config = MCPConfigAddConfig.from_dict(obj.get("config")) name = from_str(obj.get("name")) - return MCPConfigAddParams(config, name) + return MCPConfigAddRequest(config, name) def to_dict(self) -> dict: result: dict = {} - result["config"] = to_class(MCPConfigAddParamsConfig, self.config) + result["config"] = to_class(MCPConfigAddConfig, self.config) result["name"] = from_str(self.name) return result - @dataclass -class MCPConfigUpdateParamsConfig: +class MCPConfigUpdateConfig: """MCP server configuration (local/stdio or remote/http)""" args: list[str] | None = None command: str | None = None cwd: str | None = None env: dict[str, str] | None = None - filter_mapping: dict[str, FilterMappingEnum] | FilterMappingEnum | None = None + filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None is_default_server: bool | None = None - timeout: float | None = None + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + tools: list[str] | None = None """Tools to include. Defaults to all tools if not specified.""" - type: ServerType | None = None + type: MCPConfigType | None = None headers: dict[str, str] | None = None oauth_client_id: str | None = None oauth_public_client: bool | None = None url: str | None = None @staticmethod - def from_dict(obj: Any) -> 'MCPConfigUpdateParamsConfig': + def from_dict(obj: Any) -> 'MCPConfigUpdateConfig': assert isinstance(obj, dict) args = from_union([lambda x: from_list(from_str, x), from_none], obj.get("args")) command = from_union([from_str, from_none], obj.get("command")) cwd = from_union([from_str, from_none], obj.get("cwd")) env = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("env")) - filter_mapping = from_union([lambda x: from_dict(FilterMappingEnum, x), FilterMappingEnum, from_none], obj.get("filterMapping")) + filter_mapping = from_union([lambda x: from_dict(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, from_none], obj.get("filterMapping")) is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - timeout = from_union([from_float, from_none], obj.get("timeout")) + timeout = from_union([from_int, from_none], obj.get("timeout")) tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - type = from_union([ServerType, from_none], obj.get("type")) + type = from_union([MCPConfigType, from_none], obj.get("type")) headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers")) oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId")) oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) url = from_union([from_str, from_none], obj.get("url")) - return MCPConfigUpdateParamsConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) + return MCPConfigUpdateConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url) def to_dict(self) -> dict: result: dict = {} @@ -731,15 +696,15 @@ def to_dict(self) -> dict: if self.env is not None: result["env"] = from_union([lambda x: from_dict(from_str, x), from_none], self.env) if self.filter_mapping is not None: - result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(FilterMappingEnum, x), x), lambda x: to_enum(FilterMappingEnum, x), from_none], self.filter_mapping) + result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping) if self.is_default_server is not None: result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) if self.timeout is not None: - result["timeout"] = from_union([to_float, from_none], self.timeout) + result["timeout"] = from_union([from_int, from_none], self.timeout) if self.tools is not None: result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) if self.type is not None: - result["type"] = from_union([lambda x: to_enum(ServerType, x), from_none], self.type) + result["type"] = from_union([lambda x: to_enum(MCPConfigType, x), from_none], self.type) if self.headers is not None: result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers) if self.oauth_client_id is not None: @@ -750,54 +715,58 @@ def to_dict(self) -> dict: result["url"] = from_union([from_str, from_none], self.url) return result - @dataclass -class MCPConfigUpdateParams: - config: MCPConfigUpdateParamsConfig - """MCP server configuration (local/stdio or remote/http)""" - +class MCPConfigUpdateRequest: + config: MCPConfigUpdateConfig name: str """Name of the MCP server to update""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigUpdateParams': + def from_dict(obj: Any) -> 'MCPConfigUpdateRequest': assert isinstance(obj, dict) - config = MCPConfigUpdateParamsConfig.from_dict(obj.get("config")) + config = MCPConfigUpdateConfig.from_dict(obj.get("config")) name = from_str(obj.get("name")) - return MCPConfigUpdateParams(config, name) + return MCPConfigUpdateRequest(config, name) def to_dict(self) -> dict: result: dict = {} - result["config"] = to_class(MCPConfigUpdateParamsConfig, self.config) + result["config"] = to_class(MCPConfigUpdateConfig, self.config) result["name"] = from_str(self.name) return result - @dataclass -class MCPConfigRemoveParams: +class MCPConfigRemoveRequest: name: str """Name of the MCP server to remove""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigRemoveParams': + def from_dict(obj: Any) -> 'MCPConfigRemoveRequest': assert isinstance(obj, dict) name = from_str(obj.get("name")) - return MCPConfigRemoveParams(name) + return MCPConfigRemoveRequest(name) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) return result - -class ServerSource(Enum): - """Configuration source""" - +class MCPServerSource(Enum): + """Configuration source + + Configuration source: user, workspace, plugin, or builtin + """ BUILTIN = "builtin" PLUGIN = "plugin" USER = "user" WORKSPACE = "workspace" +class DiscoveredMCPServerType(Enum): + """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)""" + + HTTP = "http" + MEMORY = "memory" + SSE = "sse" + STDIO = "stdio" @dataclass class DiscoveredMCPServer: @@ -807,31 +776,27 @@ class DiscoveredMCPServer: name: str """Server name (config key)""" - source: ServerSource - """Configuration source""" - - type: str | None = None - """Server type: local, stdio, http, or sse""" + source: MCPServerSource + type: DiscoveredMCPServerType | None = None @staticmethod def from_dict(obj: Any) -> 'DiscoveredMCPServer': assert isinstance(obj, dict) enabled = from_bool(obj.get("enabled")) name = from_str(obj.get("name")) - source = ServerSource(obj.get("source")) - type = from_union([from_str, from_none], obj.get("type")) + source = MCPServerSource(obj.get("source")) + type = from_union([DiscoveredMCPServerType, from_none], obj.get("type")) return DiscoveredMCPServer(enabled, name, source, type) def to_dict(self) -> dict: result: dict = {} result["enabled"] = from_bool(self.enabled) result["name"] = from_str(self.name) - result["source"] = to_enum(ServerSource, self.source) + result["source"] = to_enum(MCPServerSource, self.source) if self.type is not None: - result["type"] = from_union([from_str, from_none], self.type) + result["type"] = from_union([lambda x: to_enum(DiscoveredMCPServerType, x), from_none], self.type) return result - @dataclass class MCPDiscoverResult: servers: list[DiscoveredMCPServer] @@ -848,17 +813,16 @@ def to_dict(self) -> dict: result["servers"] = from_list(lambda x: to_class(DiscoveredMCPServer, x), self.servers) return result - @dataclass -class MCPDiscoverParams: +class MCPDiscoverRequest: working_directory: str | None = None """Working directory used as context for discovery (e.g., plugin resolution)""" @staticmethod - def from_dict(obj: Any) -> 'MCPDiscoverParams': + def from_dict(obj: Any) -> 'MCPDiscoverRequest': assert isinstance(obj, dict) working_directory = from_union([from_str, from_none], obj.get("workingDirectory")) - return MCPDiscoverParams(working_directory) + return MCPDiscoverRequest(working_directory) def to_dict(self) -> dict: result: dict = {} @@ -866,7 +830,6 @@ def to_dict(self) -> dict: result["workingDirectory"] = from_union([from_str, from_none], self.working_directory) return result - @dataclass class SessionFSSetProviderResult: success: bool @@ -883,19 +846,15 @@ def to_dict(self) -> dict: result["success"] = from_bool(self.success) return result - -class Conventions(Enum): +class SessionFSSetProviderConventions(Enum): """Path conventions used by this filesystem""" POSIX = "posix" WINDOWS = "windows" - @dataclass -class SessionFSSetProviderParams: - conventions: Conventions - """Path conventions used by this filesystem""" - +class SessionFSSetProviderRequest: + conventions: SessionFSSetProviderConventions initial_cwd: str """Initial working directory for sessions""" @@ -903,21 +862,20 @@ class SessionFSSetProviderParams: """Path within each session's SessionFs where the runtime stores files for that session""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSSetProviderParams': + def from_dict(obj: Any) -> 'SessionFSSetProviderRequest': assert isinstance(obj, dict) - conventions = Conventions(obj.get("conventions")) + conventions = SessionFSSetProviderConventions(obj.get("conventions")) initial_cwd = from_str(obj.get("initialCwd")) session_state_path = from_str(obj.get("sessionStatePath")) - return SessionFSSetProviderParams(conventions, initial_cwd, session_state_path) + return SessionFSSetProviderRequest(conventions, initial_cwd, session_state_path) def to_dict(self) -> dict: result: dict = {} - result["conventions"] = to_enum(Conventions, self.conventions) + result["conventions"] = to_enum(SessionFSSetProviderConventions, self.conventions) result["initialCwd"] = from_str(self.initial_cwd) result["sessionStatePath"] = from_str(self.session_state_path) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SessionsForkResult: @@ -935,10 +893,9 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionsForkParams: +class SessionsForkRequest: session_id: str """Source session ID to fork from""" @@ -948,11 +905,11 @@ class SessionsForkParams: """ @staticmethod - def from_dict(obj: Any) -> 'SessionsForkParams': + def from_dict(obj: Any) -> 'SessionsForkRequest': assert isinstance(obj, dict) session_id = from_str(obj.get("sessionId")) to_event_id = from_union([from_str, from_none], obj.get("toEventId")) - return SessionsForkParams(session_id, to_event_id) + return SessionsForkRequest(session_id, to_event_id) def to_dict(self) -> dict: result: dict = {} @@ -961,17 +918,16 @@ def to_dict(self) -> dict: result["toEventId"] = from_union([from_str, from_none], self.to_event_id) return result - @dataclass -class SessionModelGetCurrentResult: +class ModelCurrent: model_id: str | None = None """Currently active model identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionModelGetCurrentResult': + def from_dict(obj: Any) -> 'ModelCurrent': assert isinstance(obj, dict) model_id = from_union([from_str, from_none], obj.get("modelId")) - return SessionModelGetCurrentResult(model_id) + return ModelCurrent(model_id) def to_dict(self) -> dict: result: dict = {} @@ -979,17 +935,16 @@ def to_dict(self) -> dict: result["modelId"] = from_union([from_str, from_none], self.model_id) return result - @dataclass -class SessionModelSwitchToResult: +class ModelSwitchToResult: model_id: str | None = None """Currently active model identifier after the switch""" @staticmethod - def from_dict(obj: Any) -> 'SessionModelSwitchToResult': + def from_dict(obj: Any) -> 'ModelSwitchToResult': assert isinstance(obj, dict) model_id = from_union([from_str, from_none], obj.get("modelId")) - return SessionModelSwitchToResult(model_id) + return ModelSwitchToResult(model_id) def to_dict(self) -> dict: result: dict = {} @@ -997,13 +952,12 @@ def to_dict(self) -> dict: result["modelId"] = from_union([from_str, from_none], self.model_id) return result - @dataclass class ModelCapabilitiesOverrideLimitsVision: - max_prompt_image_size: float | None = None + max_prompt_image_size: int | None = None """Maximum image size in bytes""" - max_prompt_images: float | None = None + max_prompt_images: int | None = None """Maximum number of images per prompt""" supported_media_types: list[str] | None = None @@ -1012,55 +966,53 @@ class ModelCapabilitiesOverrideLimitsVision: @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimitsVision': assert isinstance(obj, dict) - max_prompt_image_size = from_union([from_float, from_none], obj.get("max_prompt_image_size")) - max_prompt_images = from_union([from_float, from_none], obj.get("max_prompt_images")) + max_prompt_image_size = from_union([from_int, from_none], obj.get("max_prompt_image_size")) + max_prompt_images = from_union([from_int, from_none], obj.get("max_prompt_images")) supported_media_types = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supported_media_types")) return ModelCapabilitiesOverrideLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types) def to_dict(self) -> dict: result: dict = {} if self.max_prompt_image_size is not None: - result["max_prompt_image_size"] = from_union([to_float, from_none], self.max_prompt_image_size) + result["max_prompt_image_size"] = from_union([from_int, from_none], self.max_prompt_image_size) if self.max_prompt_images is not None: - result["max_prompt_images"] = from_union([to_float, from_none], self.max_prompt_images) + result["max_prompt_images"] = from_union([from_int, from_none], self.max_prompt_images) if self.supported_media_types is not None: result["supported_media_types"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_media_types) return result - @dataclass class ModelCapabilitiesOverrideLimits: """Token limits for prompts, outputs, and context window""" - max_context_window_tokens: float | None = None + max_context_window_tokens: int | None = None """Maximum total context window size in tokens""" - max_output_tokens: float | None = None - max_prompt_tokens: float | None = None + max_output_tokens: int | None = None + max_prompt_tokens: int | None = None vision: ModelCapabilitiesOverrideLimitsVision | None = None @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimits': assert isinstance(obj, dict) - max_context_window_tokens = from_union([from_float, from_none], obj.get("max_context_window_tokens")) - max_output_tokens = from_union([from_float, from_none], obj.get("max_output_tokens")) - max_prompt_tokens = from_union([from_float, from_none], obj.get("max_prompt_tokens")) + max_context_window_tokens = from_union([from_int, from_none], obj.get("max_context_window_tokens")) + max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) + max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) vision = from_union([ModelCapabilitiesOverrideLimitsVision.from_dict, from_none], obj.get("vision")) return ModelCapabilitiesOverrideLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) def to_dict(self) -> dict: result: dict = {} if self.max_context_window_tokens is not None: - result["max_context_window_tokens"] = from_union([to_float, from_none], self.max_context_window_tokens) + result["max_context_window_tokens"] = from_union([from_int, from_none], self.max_context_window_tokens) if self.max_output_tokens is not None: - result["max_output_tokens"] = from_union([to_float, from_none], self.max_output_tokens) + result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) if self.max_prompt_tokens is not None: - result["max_prompt_tokens"] = from_union([to_float, from_none], self.max_prompt_tokens) + result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) if self.vision is not None: result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideLimitsVision, x), from_none], self.vision) return result - @dataclass class ModelCapabilitiesOverrideSupports: """Feature flags indicating what the model supports""" @@ -1083,16 +1035,12 @@ def to_dict(self) -> dict: result["vision"] = from_union([from_bool, from_none], self.vision) return result - @dataclass class ModelCapabilitiesOverride: """Override individual model capabilities resolved by the runtime""" limits: ModelCapabilitiesOverrideLimits | None = None - """Token limits for prompts, outputs, and context window""" - supports: ModelCapabilitiesOverrideSupports | None = None - """Feature flags indicating what the model supports""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesOverride': @@ -1109,25 +1057,22 @@ def to_dict(self) -> dict: result["supports"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideSupports, x), from_none], self.supports) return result - @dataclass -class SessionModelSwitchToParams: +class ModelSwitchToRequest: model_id: str """Model identifier to switch to""" model_capabilities: ModelCapabilitiesOverride | None = None - """Override individual model capabilities resolved by the runtime""" - reasoning_effort: str | None = None """Reasoning effort level to use for the model""" @staticmethod - def from_dict(obj: Any) -> 'SessionModelSwitchToParams': + def from_dict(obj: Any) -> 'ModelSwitchToRequest': assert isinstance(obj, dict) model_id = from_str(obj.get("modelId")) model_capabilities = from_union([ModelCapabilitiesOverride.from_dict, from_none], obj.get("modelCapabilities")) reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort")) - return SessionModelSwitchToParams(model_id, model_capabilities, reasoning_effort) + return ModelSwitchToRequest(model_id, model_capabilities, reasoning_effort) def to_dict(self) -> dict: result: dict = {} @@ -1138,72 +1083,30 @@ def to_dict(self) -> dict: result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort) return result +class SessionMode(Enum): + """The agent mode. Valid values: "interactive", "plan", "autopilot".""" -class Mode(Enum): - """The current agent mode. - - The agent mode after switching. - - The mode to switch to. Valid values: "interactive", "plan", "autopilot". - """ AUTOPILOT = "autopilot" INTERACTIVE = "interactive" PLAN = "plan" - -@dataclass -class SessionModeGetResult: - mode: Mode - """The current agent mode.""" - - @staticmethod - def from_dict(obj: Any) -> 'SessionModeGetResult': - assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeGetResult(mode) - - def to_dict(self) -> dict: - result: dict = {} - result["mode"] = to_enum(Mode, self.mode) - return result - - @dataclass -class SessionModeSetResult: - mode: Mode - """The agent mode after switching.""" +class ModeSetRequest: + mode: SessionMode @staticmethod - def from_dict(obj: Any) -> 'SessionModeSetResult': + def from_dict(obj: Any) -> 'ModeSetRequest': assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeSetResult(mode) + mode = SessionMode(obj.get("mode")) + return ModeSetRequest(mode) def to_dict(self) -> dict: result: dict = {} - result["mode"] = to_enum(Mode, self.mode) + result["mode"] = to_enum(SessionMode, self.mode) return result - @dataclass -class SessionModeSetParams: - mode: Mode - """The mode to switch to. Valid values: "interactive", "plan", "autopilot".""" - - @staticmethod - def from_dict(obj: Any) -> 'SessionModeSetParams': - assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeSetParams(mode) - - def to_dict(self) -> dict: - result: dict = {} - result["mode"] = to_enum(Mode, self.mode) - return result - - -@dataclass -class SessionPlanReadResult: +class Plan: exists: bool """Whether the plan file exists in the workspace""" @@ -1214,12 +1117,12 @@ class SessionPlanReadResult: """Absolute file path of the plan file, or null if workspace is not enabled""" @staticmethod - def from_dict(obj: Any) -> 'SessionPlanReadResult': + def from_dict(obj: Any) -> 'Plan': assert isinstance(obj, dict) exists = from_bool(obj.get("exists")) content = from_union([from_none, from_str], obj.get("content")) path = from_union([from_none, from_str], obj.get("path")) - return SessionPlanReadResult(exists, content, path) + return Plan(exists, content, path) def to_dict(self) -> dict: result: dict = {} @@ -1228,113 +1131,105 @@ def to_dict(self) -> dict: result["path"] = from_union([from_none, from_str], self.path) return result - @dataclass -class SessionPlanUpdateResult: +class PlanUpdateResult: @staticmethod - def from_dict(obj: Any) -> 'SessionPlanUpdateResult': + def from_dict(obj: Any) -> 'PlanUpdateResult': assert isinstance(obj, dict) - return SessionPlanUpdateResult() + return PlanUpdateResult() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionPlanUpdateParams: +class PlanUpdateRequest: content: str """The new content for the plan file""" @staticmethod - def from_dict(obj: Any) -> 'SessionPlanUpdateParams': + def from_dict(obj: Any) -> 'PlanUpdateRequest': assert isinstance(obj, dict) content = from_str(obj.get("content")) - return SessionPlanUpdateParams(content) + return PlanUpdateRequest(content) def to_dict(self) -> dict: result: dict = {} result["content"] = from_str(self.content) return result - @dataclass -class SessionPlanDeleteResult: +class PlanDelete: @staticmethod - def from_dict(obj: Any) -> 'SessionPlanDeleteResult': + def from_dict(obj: Any) -> 'PlanDelete': assert isinstance(obj, dict) - return SessionPlanDeleteResult() + return PlanDelete() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionWorkspaceListFilesResult: +class WorkspaceFiles: files: list[str] """Relative file paths in the workspace files directory""" @staticmethod - def from_dict(obj: Any) -> 'SessionWorkspaceListFilesResult': + def from_dict(obj: Any) -> 'WorkspaceFiles': assert isinstance(obj, dict) files = from_list(from_str, obj.get("files")) - return SessionWorkspaceListFilesResult(files) + return WorkspaceFiles(files) def to_dict(self) -> dict: result: dict = {} result["files"] = from_list(from_str, self.files) return result - @dataclass -class SessionWorkspaceReadFileResult: +class WorkspaceReadFileResult: content: str """File content as a UTF-8 string""" @staticmethod - def from_dict(obj: Any) -> 'SessionWorkspaceReadFileResult': + def from_dict(obj: Any) -> 'WorkspaceReadFileResult': assert isinstance(obj, dict) content = from_str(obj.get("content")) - return SessionWorkspaceReadFileResult(content) + return WorkspaceReadFileResult(content) def to_dict(self) -> dict: result: dict = {} result["content"] = from_str(self.content) return result - @dataclass -class SessionWorkspaceReadFileParams: +class WorkspaceReadFileRequest: path: str """Relative path within the workspace files directory""" @staticmethod - def from_dict(obj: Any) -> 'SessionWorkspaceReadFileParams': + def from_dict(obj: Any) -> 'WorkspaceReadFileRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) - return SessionWorkspaceReadFileParams(path) + return WorkspaceReadFileRequest(path) def to_dict(self) -> dict: result: dict = {} result["path"] = from_str(self.path) return result - @dataclass -class SessionWorkspaceCreateFileResult: +class WorkspaceCreateFileResult: @staticmethod - def from_dict(obj: Any) -> 'SessionWorkspaceCreateFileResult': + def from_dict(obj: Any) -> 'WorkspaceCreateFileResult': assert isinstance(obj, dict) - return SessionWorkspaceCreateFileResult() + return WorkspaceCreateFileResult() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionWorkspaceCreateFileParams: +class WorkspaceCreateFileRequest: content: str """File content to write as a UTF-8 string""" @@ -1342,11 +1237,11 @@ class SessionWorkspaceCreateFileParams: """Relative path within the workspace files directory""" @staticmethod - def from_dict(obj: Any) -> 'SessionWorkspaceCreateFileParams': + def from_dict(obj: Any) -> 'WorkspaceCreateFileRequest': assert isinstance(obj, dict) content = from_str(obj.get("content")) path = from_str(obj.get("path")) - return SessionWorkspaceCreateFileParams(content, path) + return WorkspaceCreateFileRequest(content, path) def to_dict(self) -> dict: result: dict = {} @@ -1354,36 +1249,34 @@ def to_dict(self) -> dict: result["path"] = from_str(self.path) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionFleetStartResult: +class FleetStartResult: started: bool """Whether fleet mode was successfully activated""" @staticmethod - def from_dict(obj: Any) -> 'SessionFleetStartResult': + def from_dict(obj: Any) -> 'FleetStartResult': assert isinstance(obj, dict) started = from_bool(obj.get("started")) - return SessionFleetStartResult(started) + return FleetStartResult(started) def to_dict(self) -> dict: result: dict = {} result["started"] = from_bool(self.started) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionFleetStartParams: +class FleetStartRequest: prompt: str | None = None """Optional user prompt to combine with fleet instructions""" @staticmethod - def from_dict(obj: Any) -> 'SessionFleetStartParams': + def from_dict(obj: Any) -> 'FleetStartRequest': assert isinstance(obj, dict) prompt = from_union([from_str, from_none], obj.get("prompt")) - return SessionFleetStartParams(prompt) + return FleetStartRequest(prompt) def to_dict(self) -> dict: result: dict = {} @@ -1391,9 +1284,8 @@ def to_dict(self) -> dict: result["prompt"] = from_union([from_str, from_none], self.prompt) return result - @dataclass -class SessionAgentListResultAgent: +class Agent: description: str """Description of the agent's purpose""" @@ -1404,12 +1296,12 @@ class SessionAgentListResultAgent: """Unique identifier of the custom agent""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentListResultAgent': + def from_dict(obj: Any) -> 'Agent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - return SessionAgentListResultAgent(description, display_name, name) + return Agent(description, display_name, name) def to_dict(self) -> dict: result: dict = {} @@ -1418,27 +1310,25 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentListResult: - agents: list[SessionAgentListResultAgent] +class AgentList: + agents: list[Agent] """Available custom agents""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentListResult': + def from_dict(obj: Any) -> 'AgentList': assert isinstance(obj, dict) - agents = from_list(SessionAgentListResultAgent.from_dict, obj.get("agents")) - return SessionAgentListResult(agents) + agents = from_list(Agent.from_dict, obj.get("agents")) + return AgentList(agents) def to_dict(self) -> dict: result: dict = {} - result["agents"] = from_list(lambda x: to_class(SessionAgentListResultAgent, x), self.agents) + result["agents"] = from_list(lambda x: to_class(Agent, x), self.agents) return result - @dataclass -class SessionAgentGetCurrentResultAgent: +class AgentCurrentAgent: description: str """Description of the agent's purpose""" @@ -1449,12 +1339,12 @@ class SessionAgentGetCurrentResultAgent: """Unique identifier of the custom agent""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentGetCurrentResultAgent': + def from_dict(obj: Any) -> 'AgentCurrentAgent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - return SessionAgentGetCurrentResultAgent(description, display_name, name) + return AgentCurrentAgent(description, display_name, name) def to_dict(self) -> dict: result: dict = {} @@ -1463,27 +1353,25 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentGetCurrentResult: - agent: SessionAgentGetCurrentResultAgent | None = None +class AgentCurrent: + agent: AgentCurrentAgent | None = None """Currently selected custom agent, or null if using the default agent""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentGetCurrentResult': + def from_dict(obj: Any) -> 'AgentCurrent': assert isinstance(obj, dict) - agent = from_union([SessionAgentGetCurrentResultAgent.from_dict, from_none], obj.get("agent")) - return SessionAgentGetCurrentResult(agent) + agent = from_union([AgentCurrentAgent.from_dict, from_none], obj.get("agent")) + return AgentCurrent(agent) def to_dict(self) -> dict: result: dict = {} - result["agent"] = from_union([lambda x: to_class(SessionAgentGetCurrentResultAgent, x), from_none], self.agent) + result["agent"] = from_union([lambda x: to_class(AgentCurrentAgent, x), from_none], self.agent) return result - @dataclass -class SessionAgentSelectResultAgent: +class AgentSelectAgent: """The newly selected custom agent""" description: str @@ -1496,12 +1384,12 @@ class SessionAgentSelectResultAgent: """Unique identifier of the custom agent""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentSelectResultAgent': + def from_dict(obj: Any) -> 'AgentSelectAgent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - return SessionAgentSelectResultAgent(description, display_name, name) + return AgentSelectAgent(description, display_name, name) def to_dict(self) -> dict: result: dict = {} @@ -1510,58 +1398,53 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentSelectResult: - agent: SessionAgentSelectResultAgent - """The newly selected custom agent""" +class AgentSelectResult: + agent: AgentSelectAgent @staticmethod - def from_dict(obj: Any) -> 'SessionAgentSelectResult': + def from_dict(obj: Any) -> 'AgentSelectResult': assert isinstance(obj, dict) - agent = SessionAgentSelectResultAgent.from_dict(obj.get("agent")) - return SessionAgentSelectResult(agent) + agent = AgentSelectAgent.from_dict(obj.get("agent")) + return AgentSelectResult(agent) def to_dict(self) -> dict: result: dict = {} - result["agent"] = to_class(SessionAgentSelectResultAgent, self.agent) + result["agent"] = to_class(AgentSelectAgent, self.agent) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentSelectParams: +class AgentSelectRequest: name: str """Name of the custom agent to select""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentSelectParams': + def from_dict(obj: Any) -> 'AgentSelectRequest': assert isinstance(obj, dict) name = from_str(obj.get("name")) - return SessionAgentSelectParams(name) + return AgentSelectRequest(name) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentDeselectResult: +class AgentDeselect: @staticmethod - def from_dict(obj: Any) -> 'SessionAgentDeselectResult': + def from_dict(obj: Any) -> 'AgentDeselect': assert isinstance(obj, dict) - return SessionAgentDeselectResult() + return AgentDeselect() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionAgentReloadResultAgent: +class AgentReloadAgent: description: str """Description of the agent's purpose""" @@ -1572,12 +1455,12 @@ class SessionAgentReloadResultAgent: """Unique identifier of the custom agent""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentReloadResultAgent': + def from_dict(obj: Any) -> 'AgentReloadAgent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - return SessionAgentReloadResultAgent(description, display_name, name) + return AgentReloadAgent(description, display_name, name) def to_dict(self) -> dict: result: dict = {} @@ -1586,25 +1469,23 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAgentReloadResult: - agents: list[SessionAgentReloadResultAgent] +class AgentReload: + agents: list[AgentReloadAgent] """Reloaded custom agents""" @staticmethod - def from_dict(obj: Any) -> 'SessionAgentReloadResult': + def from_dict(obj: Any) -> 'AgentReload': assert isinstance(obj, dict) - agents = from_list(SessionAgentReloadResultAgent.from_dict, obj.get("agents")) - return SessionAgentReloadResult(agents) + agents = from_list(AgentReloadAgent.from_dict, obj.get("agents")) + return AgentReload(agents) def to_dict(self) -> dict: result: dict = {} - result["agents"] = from_list(lambda x: to_class(SessionAgentReloadResultAgent, x), self.agents) + result["agents"] = from_list(lambda x: to_class(AgentReloadAgent, x), self.agents) return result - @dataclass class Skill: description: str @@ -1647,101 +1528,94 @@ def to_dict(self) -> dict: result["path"] = from_union([from_str, from_none], self.path) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsListResult: +class SkillList: skills: list[Skill] """Available skills""" @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsListResult': + def from_dict(obj: Any) -> 'SkillList': assert isinstance(obj, dict) skills = from_list(Skill.from_dict, obj.get("skills")) - return SessionSkillsListResult(skills) + return SkillList(skills) def to_dict(self) -> dict: result: dict = {} result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsEnableResult: +class SkillsEnableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsEnableResult': + def from_dict(obj: Any) -> 'SkillsEnableResult': assert isinstance(obj, dict) - return SessionSkillsEnableResult() + return SkillsEnableResult() def to_dict(self) -> dict: result: dict = {} return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsEnableParams: +class SkillsEnableRequest: name: str """Name of the skill to enable""" @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsEnableParams': + def from_dict(obj: Any) -> 'SkillsEnableRequest': assert isinstance(obj, dict) name = from_str(obj.get("name")) - return SessionSkillsEnableParams(name) + return SkillsEnableRequest(name) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsDisableResult: +class SkillsDisableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsDisableResult': + def from_dict(obj: Any) -> 'SkillsDisableResult': assert isinstance(obj, dict) - return SessionSkillsDisableResult() + return SkillsDisableResult() def to_dict(self) -> dict: result: dict = {} return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsDisableParams: +class SkillsDisableRequest: name: str """Name of the skill to disable""" @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsDisableParams': + def from_dict(obj: Any) -> 'SkillsDisableRequest': assert isinstance(obj, dict) name = from_str(obj.get("name")) - return SessionSkillsDisableParams(name) + return SkillsDisableRequest(name) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionSkillsReloadResult: +class SkillsReload: @staticmethod - def from_dict(obj: Any) -> 'SessionSkillsReloadResult': + def from_dict(obj: Any) -> 'SkillsReload': assert isinstance(obj, dict) - return SessionSkillsReloadResult() + return SkillsReload() def to_dict(self) -> dict: result: dict = {} return result - -class ServerStatus(Enum): +class MCPServerStatus(Enum): """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" CONNECTED = "connected" @@ -1751,128 +1625,117 @@ class ServerStatus(Enum): NOT_CONFIGURED = "not_configured" PENDING = "pending" - @dataclass -class ServerElement: +class MCPServer: name: str """Server name (config key)""" - status: ServerStatus - """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" - + status: MCPServerStatus error: str | None = None """Error message if the server failed to connect""" - source: str | None = None - """Configuration source: user, workspace, plugin, or builtin""" + source: MCPServerSource | None = None @staticmethod - def from_dict(obj: Any) -> 'ServerElement': + def from_dict(obj: Any) -> 'MCPServer': assert isinstance(obj, dict) name = from_str(obj.get("name")) - status = ServerStatus(obj.get("status")) + status = MCPServerStatus(obj.get("status")) error = from_union([from_str, from_none], obj.get("error")) - source = from_union([from_str, from_none], obj.get("source")) - return ServerElement(name, status, error, source) + source = from_union([MCPServerSource, from_none], obj.get("source")) + return MCPServer(name, status, error, source) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) - result["status"] = to_enum(ServerStatus, self.status) + result["status"] = to_enum(MCPServerStatus, self.status) if self.error is not None: result["error"] = from_union([from_str, from_none], self.error) if self.source is not None: - result["source"] = from_union([from_str, from_none], self.source) + result["source"] = from_union([lambda x: to_enum(MCPServerSource, x), from_none], self.source) return result - @dataclass -class SessionMCPListResult: - servers: list[ServerElement] +class MCPList: + servers: list[MCPServer] """Configured MCP servers""" @staticmethod - def from_dict(obj: Any) -> 'SessionMCPListResult': + def from_dict(obj: Any) -> 'MCPList': assert isinstance(obj, dict) - servers = from_list(ServerElement.from_dict, obj.get("servers")) - return SessionMCPListResult(servers) + servers = from_list(MCPServer.from_dict, obj.get("servers")) + return MCPList(servers) def to_dict(self) -> dict: result: dict = {} - result["servers"] = from_list(lambda x: to_class(ServerElement, x), self.servers) + result["servers"] = from_list(lambda x: to_class(MCPServer, x), self.servers) return result - @dataclass -class SessionMCPEnableResult: +class MCPEnableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionMCPEnableResult': + def from_dict(obj: Any) -> 'MCPEnableResult': assert isinstance(obj, dict) - return SessionMCPEnableResult() + return MCPEnableResult() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionMCPEnableParams: +class MCPEnableRequest: server_name: str """Name of the MCP server to enable""" @staticmethod - def from_dict(obj: Any) -> 'SessionMCPEnableParams': + def from_dict(obj: Any) -> 'MCPEnableRequest': assert isinstance(obj, dict) server_name = from_str(obj.get("serverName")) - return SessionMCPEnableParams(server_name) + return MCPEnableRequest(server_name) def to_dict(self) -> dict: result: dict = {} result["serverName"] = from_str(self.server_name) return result - @dataclass -class SessionMCPDisableResult: +class MCPDisableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionMCPDisableResult': + def from_dict(obj: Any) -> 'MCPDisableResult': assert isinstance(obj, dict) - return SessionMCPDisableResult() + return MCPDisableResult() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionMCPDisableParams: +class MCPDisableRequest: server_name: str """Name of the MCP server to disable""" @staticmethod - def from_dict(obj: Any) -> 'SessionMCPDisableParams': + def from_dict(obj: Any) -> 'MCPDisableRequest': assert isinstance(obj, dict) server_name = from_str(obj.get("serverName")) - return SessionMCPDisableParams(server_name) + return MCPDisableRequest(server_name) def to_dict(self) -> dict: result: dict = {} result["serverName"] = from_str(self.server_name) return result - @dataclass -class SessionMCPReloadResult: +class MCPReload: @staticmethod - def from_dict(obj: Any) -> 'SessionMCPReloadResult': + def from_dict(obj: Any) -> 'MCPReload': assert isinstance(obj, dict) - return SessionMCPReloadResult() + return MCPReload() def to_dict(self) -> dict: result: dict = {} return result - @dataclass class Plugin: enabled: bool @@ -1905,32 +1768,29 @@ def to_dict(self) -> dict: result["version"] = from_union([from_str, from_none], self.version) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionPluginsListResult: +class PluginList: plugins: list[Plugin] """Installed plugins""" @staticmethod - def from_dict(obj: Any) -> 'SessionPluginsListResult': + def from_dict(obj: Any) -> 'PluginList': assert isinstance(obj, dict) plugins = from_list(Plugin.from_dict, obj.get("plugins")) - return SessionPluginsListResult(plugins) + return PluginList(plugins) def to_dict(self) -> dict: result: dict = {} result["plugins"] = from_list(lambda x: to_class(Plugin, x), self.plugins) return result - class ExtensionSource(Enum): """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" PROJECT = "project" USER = "user" - class ExtensionStatus(Enum): """Current status: running, disabled, failed, or starting""" @@ -1939,7 +1799,6 @@ class ExtensionStatus(Enum): RUNNING = "running" STARTING = "starting" - @dataclass class Extension: id: str @@ -1949,11 +1808,7 @@ class Extension: """Extension name (directory name)""" source: ExtensionSource - """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" - status: ExtensionStatus - """Current status: running, disabled, failed, or starting""" - pid: int | None = None """Process ID if the extension is running""" @@ -1977,119 +1832,111 @@ def to_dict(self) -> dict: result["pid"] = from_union([from_int, from_none], self.pid) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsListResult: +class ExtensionList: extensions: list[Extension] """Discovered extensions and their current status""" @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsListResult': + def from_dict(obj: Any) -> 'ExtensionList': assert isinstance(obj, dict) extensions = from_list(Extension.from_dict, obj.get("extensions")) - return SessionExtensionsListResult(extensions) + return ExtensionList(extensions) def to_dict(self) -> dict: result: dict = {} result["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsEnableResult: +class ExtensionsEnableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsEnableResult': + def from_dict(obj: Any) -> 'ExtensionsEnableResult': assert isinstance(obj, dict) - return SessionExtensionsEnableResult() + return ExtensionsEnableResult() def to_dict(self) -> dict: result: dict = {} return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsEnableParams: +class ExtensionsEnableRequest: id: str """Source-qualified extension ID to enable""" @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsEnableParams': + def from_dict(obj: Any) -> 'ExtensionsEnableRequest': assert isinstance(obj, dict) id = from_str(obj.get("id")) - return SessionExtensionsEnableParams(id) + return ExtensionsEnableRequest(id) def to_dict(self) -> dict: result: dict = {} result["id"] = from_str(self.id) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsDisableResult: +class ExtensionsDisableResult: @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsDisableResult': + def from_dict(obj: Any) -> 'ExtensionsDisableResult': assert isinstance(obj, dict) - return SessionExtensionsDisableResult() + return ExtensionsDisableResult() def to_dict(self) -> dict: result: dict = {} return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsDisableParams: +class ExtensionsDisableRequest: id: str """Source-qualified extension ID to disable""" @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsDisableParams': + def from_dict(obj: Any) -> 'ExtensionsDisableRequest': assert isinstance(obj, dict) id = from_str(obj.get("id")) - return SessionExtensionsDisableParams(id) + return ExtensionsDisableRequest(id) def to_dict(self) -> dict: result: dict = {} result["id"] = from_str(self.id) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionExtensionsReloadResult: +class ExtensionsReload: @staticmethod - def from_dict(obj: Any) -> 'SessionExtensionsReloadResult': + def from_dict(obj: Any) -> 'ExtensionsReload': assert isinstance(obj, dict) - return SessionExtensionsReloadResult() + return ExtensionsReload() def to_dict(self) -> dict: result: dict = {} return result - @dataclass -class SessionToolsHandlePendingToolCallResult: +class HandleToolCallResult: success: bool """Whether the tool call result was handled successfully""" @staticmethod - def from_dict(obj: Any) -> 'SessionToolsHandlePendingToolCallResult': + def from_dict(obj: Any) -> 'HandleToolCallResult': assert isinstance(obj, dict) success = from_bool(obj.get("success")) - return SessionToolsHandlePendingToolCallResult(success) + return HandleToolCallResult(success) def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) return result - @dataclass -class ResultResult: +class ToolCallResult: text_result_for_llm: str """Text result to send back to the LLM""" @@ -2103,13 +1950,13 @@ class ResultResult: """Telemetry data from tool execution""" @staticmethod - def from_dict(obj: Any) -> 'ResultResult': + def from_dict(obj: Any) -> 'ToolCallResult': assert isinstance(obj, dict) text_result_for_llm = from_str(obj.get("textResultForLlm")) error = from_union([from_str, from_none], obj.get("error")) result_type = from_union([from_str, from_none], obj.get("resultType")) tool_telemetry = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("toolTelemetry")) - return ResultResult(text_result_for_llm, error, result_type, tool_telemetry) + return ToolCallResult(text_result_for_llm, error, result_type, tool_telemetry) def to_dict(self) -> dict: result: dict = {} @@ -2122,25 +1969,23 @@ def to_dict(self) -> dict: result["toolTelemetry"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.tool_telemetry) return result - @dataclass -class SessionToolsHandlePendingToolCallParams: +class ToolsHandlePendingToolCallRequest: request_id: str """Request ID of the pending tool call""" error: str | None = None """Error message if the tool call failed""" - result: ResultResult | str | None = None - """Tool call result (string or expanded result object)""" + result: ToolCallResult | str | None = None @staticmethod - def from_dict(obj: Any) -> 'SessionToolsHandlePendingToolCallParams': + def from_dict(obj: Any) -> 'ToolsHandlePendingToolCallRequest': assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) error = from_union([from_str, from_none], obj.get("error")) - result = from_union([ResultResult.from_dict, from_str, from_none], obj.get("result")) - return SessionToolsHandlePendingToolCallParams(request_id, error, result) + result = from_union([ToolCallResult.from_dict, from_str, from_none], obj.get("result")) + return ToolsHandlePendingToolCallRequest(request_id, error, result) def to_dict(self) -> dict: result: dict = {} @@ -2148,29 +1993,27 @@ def to_dict(self) -> dict: if self.error is not None: result["error"] = from_union([from_str, from_none], self.error) if self.result is not None: - result["result"] = from_union([lambda x: to_class(ResultResult, x), from_str, from_none], self.result) + result["result"] = from_union([lambda x: to_class(ToolCallResult, x), from_str, from_none], self.result) return result - @dataclass -class SessionCommandsHandlePendingCommandResult: +class CommandsHandlePendingCommandResult: success: bool """Whether the command was handled successfully""" @staticmethod - def from_dict(obj: Any) -> 'SessionCommandsHandlePendingCommandResult': + def from_dict(obj: Any) -> 'CommandsHandlePendingCommandResult': assert isinstance(obj, dict) success = from_bool(obj.get("success")) - return SessionCommandsHandlePendingCommandResult(success) + return CommandsHandlePendingCommandResult(success) def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) return result - @dataclass -class SessionCommandsHandlePendingCommandParams: +class CommandsHandlePendingCommandRequest: request_id: str """Request ID from the command invocation event""" @@ -2178,11 +2021,11 @@ class SessionCommandsHandlePendingCommandParams: """Error message if the command handler failed""" @staticmethod - def from_dict(obj: Any) -> 'SessionCommandsHandlePendingCommandParams': + def from_dict(obj: Any) -> 'CommandsHandlePendingCommandRequest': assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) error = from_union([from_str, from_none], obj.get("error")) - return SessionCommandsHandlePendingCommandParams(request_id, error) + return CommandsHandlePendingCommandRequest(request_id, error) def to_dict(self) -> dict: result: dict = {} @@ -2191,56 +2034,51 @@ def to_dict(self) -> dict: result["error"] = from_union([from_str, from_none], self.error) return result - -class Action(Enum): +class ElicitationResponseAction(Enum): """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" ACCEPT = "accept" CANCEL = "cancel" DECLINE = "decline" - @dataclass -class SessionUIElicitationResult: - action: Action - """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" +class UIElicitationResponse: + """The elicitation response (accept with form values, decline, or cancel)""" + action: ElicitationResponseAction content: dict[str, float | bool | list[str] | str] | None = None - """The form values submitted by the user (present when action is 'accept')""" @staticmethod - def from_dict(obj: Any) -> 'SessionUIElicitationResult': + def from_dict(obj: Any) -> 'UIElicitationResponse': assert isinstance(obj, dict) - action = Action(obj.get("action")) + action = ElicitationResponseAction(obj.get("action")) content = from_union([lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) - return SessionUIElicitationResult(action, content) + return UIElicitationResponse(action, content) def to_dict(self) -> dict: result: dict = {} - result["action"] = to_enum(Action, self.action) + result["action"] = to_enum(ElicitationResponseAction, self.action) if self.content is not None: result["content"] = from_union([lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) return result - -class Format(Enum): +class UIElicitationSchemaPropertyStringFormat(Enum): DATE = "date" DATE_TIME = "date-time" EMAIL = "email" URI = "uri" - @dataclass -class AnyOf: +class ElicitationArrayAnyOfFieldItemsAnyOf: const: str title: str @staticmethod - def from_dict(obj: Any) -> 'AnyOf': + def from_dict(obj: Any) -> 'ElicitationArrayAnyOfFieldItemsAnyOf': assert isinstance(obj, dict) const = from_str(obj.get("const")) title = from_str(obj.get("title")) - return AnyOf(const, title) + return ElicitationArrayAnyOfFieldItemsAnyOf(const, title) def to_dict(self) -> dict: result: dict = {} @@ -2248,24 +2086,22 @@ def to_dict(self) -> dict: result["title"] = from_str(self.title) return result - class ItemsType(Enum): STRING = "string" - @dataclass -class Items: +class ElicitationArrayFieldItems: enum: list[str] | None = None type: ItemsType | None = None - any_of: list[AnyOf] | None = None + any_of: list[ElicitationArrayAnyOfFieldItemsAnyOf] | None = None @staticmethod - def from_dict(obj: Any) -> 'Items': + def from_dict(obj: Any) -> 'ElicitationArrayFieldItems': assert isinstance(obj, dict) enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) type = from_union([ItemsType, from_none], obj.get("type")) - any_of = from_union([lambda x: from_list(AnyOf.from_dict, x), from_none], obj.get("anyOf")) - return Items(enum, type, any_of) + any_of = from_union([lambda x: from_list(ElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf")) + return ElicitationArrayFieldItems(enum, type, any_of) def to_dict(self) -> dict: result: dict = {} @@ -2274,21 +2110,20 @@ def to_dict(self) -> dict: if self.type is not None: result["type"] = from_union([lambda x: to_enum(ItemsType, x), from_none], self.type) if self.any_of is not None: - result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(AnyOf, x), x), from_none], self.any_of) + result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(ElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of) return result - @dataclass -class OneOf: +class ElicitationStringOneOfFieldOneOf: const: str title: str @staticmethod - def from_dict(obj: Any) -> 'OneOf': + def from_dict(obj: Any) -> 'ElicitationStringOneOfFieldOneOf': assert isinstance(obj, dict) const = from_str(obj.get("const")) title = from_str(obj.get("title")) - return OneOf(const, title) + return ElicitationStringOneOfFieldOneOf(const, title) def to_dict(self) -> dict: result: dict = {} @@ -2296,56 +2131,54 @@ def to_dict(self) -> dict: result["title"] = from_str(self.title) return result - -class PropertyType(Enum): +class UIElicitationSchemaPropertyNumberType(Enum): ARRAY = "array" BOOLEAN = "boolean" INTEGER = "integer" NUMBER = "number" STRING = "string" - @dataclass -class Property: - type: PropertyType +class UIElicitationSchemaProperty: + type: UIElicitationSchemaPropertyNumberType default: float | bool | list[str] | str | None = None description: str | None = None enum: list[str] | None = None enum_names: list[str] | None = None title: str | None = None - one_of: list[OneOf] | None = None - items: Items | None = None + one_of: list[ElicitationStringOneOfFieldOneOf] | None = None + items: ElicitationArrayFieldItems | None = None max_items: float | None = None min_items: float | None = None - format: Format | None = None + format: UIElicitationSchemaPropertyStringFormat | None = None max_length: float | None = None min_length: float | None = None maximum: float | None = None minimum: float | None = None @staticmethod - def from_dict(obj: Any) -> 'Property': + def from_dict(obj: Any) -> 'UIElicitationSchemaProperty': assert isinstance(obj, dict) - type = PropertyType(obj.get("type")) + type = UIElicitationSchemaPropertyNumberType(obj.get("type")) default = from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], obj.get("default")) description = from_union([from_str, from_none], obj.get("description")) enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) enum_names = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enumNames")) title = from_union([from_str, from_none], obj.get("title")) - one_of = from_union([lambda x: from_list(OneOf.from_dict, x), from_none], obj.get("oneOf")) - items = from_union([Items.from_dict, from_none], obj.get("items")) + one_of = from_union([lambda x: from_list(ElicitationStringOneOfFieldOneOf.from_dict, x), from_none], obj.get("oneOf")) + items = from_union([ElicitationArrayFieldItems.from_dict, from_none], obj.get("items")) max_items = from_union([from_float, from_none], obj.get("maxItems")) min_items = from_union([from_float, from_none], obj.get("minItems")) - format = from_union([Format, from_none], obj.get("format")) + format = from_union([UIElicitationSchemaPropertyStringFormat, from_none], obj.get("format")) max_length = from_union([from_float, from_none], obj.get("maxLength")) min_length = from_union([from_float, from_none], obj.get("minLength")) maximum = from_union([from_float, from_none], obj.get("maximum")) minimum = from_union([from_float, from_none], obj.get("minimum")) - return Property(type, default, description, enum, enum_names, title, one_of, items, max_items, min_items, format, max_length, min_length, maximum, minimum) + return UIElicitationSchemaProperty(type, default, description, enum, enum_names, title, one_of, items, max_items, min_items, format, max_length, min_length, maximum, minimum) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(PropertyType, self.type) + result["type"] = to_enum(UIElicitationSchemaPropertyNumberType, self.type) if self.default is not None: result["default"] = from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], self.default) if self.description is not None: @@ -2357,15 +2190,15 @@ def to_dict(self) -> dict: if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) if self.one_of is not None: - result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(OneOf, x), x), from_none], self.one_of) + result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(ElicitationStringOneOfFieldOneOf, x), x), from_none], self.one_of) if self.items is not None: - result["items"] = from_union([lambda x: to_class(Items, x), from_none], self.items) + result["items"] = from_union([lambda x: to_class(ElicitationArrayFieldItems, x), from_none], self.items) if self.max_items is not None: result["maxItems"] = from_union([to_float, from_none], self.max_items) if self.min_items is not None: result["minItems"] = from_union([to_float, from_none], self.min_items) if self.format is not None: - result["format"] = from_union([lambda x: to_enum(Format, x), from_none], self.format) + result["format"] = from_union([lambda x: to_enum(UIElicitationSchemaPropertyStringFormat, x), from_none], self.format) if self.max_length is not None: result["maxLength"] = from_union([to_float, from_none], self.max_length) if self.min_length is not None: @@ -2376,16 +2209,14 @@ def to_dict(self) -> dict: result["minimum"] = from_union([to_float, from_none], self.minimum) return result - class RequestedSchemaType(Enum): OBJECT = "object" - @dataclass -class RequestedSchema: +class UIElicitationSchema: """JSON Schema describing the form fields to present to the user""" - properties: dict[str, Property] + properties: dict[str, UIElicitationSchemaProperty] """Form field definitions, keyed by field name""" type: RequestedSchemaType @@ -2395,127 +2226,95 @@ class RequestedSchema: """List of required field names""" @staticmethod - def from_dict(obj: Any) -> 'RequestedSchema': + def from_dict(obj: Any) -> 'UIElicitationSchema': assert isinstance(obj, dict) - properties = from_dict(Property.from_dict, obj.get("properties")) + properties = from_dict(UIElicitationSchemaProperty.from_dict, obj.get("properties")) type = RequestedSchemaType(obj.get("type")) required = from_union([lambda x: from_list(from_str, x), from_none], obj.get("required")) - return RequestedSchema(properties, type, required) + return UIElicitationSchema(properties, type, required) def to_dict(self) -> dict: result: dict = {} - result["properties"] = from_dict(lambda x: to_class(Property, x), self.properties) + result["properties"] = from_dict(lambda x: to_class(UIElicitationSchemaProperty, x), self.properties) result["type"] = to_enum(RequestedSchemaType, self.type) if self.required is not None: result["required"] = from_union([lambda x: from_list(from_str, x), from_none], self.required) return result - @dataclass -class SessionUIElicitationParams: +class UIElicitationRequest: message: str """Message describing what information is needed from the user""" - requested_schema: RequestedSchema - """JSON Schema describing the form fields to present to the user""" + requested_schema: UIElicitationSchema @staticmethod - def from_dict(obj: Any) -> 'SessionUIElicitationParams': + def from_dict(obj: Any) -> 'UIElicitationRequest': assert isinstance(obj, dict) message = from_str(obj.get("message")) - requested_schema = RequestedSchema.from_dict(obj.get("requestedSchema")) - return SessionUIElicitationParams(message, requested_schema) + requested_schema = UIElicitationSchema.from_dict(obj.get("requestedSchema")) + return UIElicitationRequest(message, requested_schema) def to_dict(self) -> dict: result: dict = {} result["message"] = from_str(self.message) - result["requestedSchema"] = to_class(RequestedSchema, self.requested_schema) + result["requestedSchema"] = to_class(UIElicitationSchema, self.requested_schema) return result - @dataclass -class SessionUIHandlePendingElicitationResult: +class UIElicitationResult: success: bool """Whether the response was accepted. False if the request was already resolved by another client. """ @staticmethod - def from_dict(obj: Any) -> 'SessionUIHandlePendingElicitationResult': + def from_dict(obj: Any) -> 'UIElicitationResult': assert isinstance(obj, dict) success = from_bool(obj.get("success")) - return SessionUIHandlePendingElicitationResult(success) + return UIElicitationResult(success) def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) return result - @dataclass -class SessionUIHandlePendingElicitationParamsResult: - """The elicitation response (accept with form values, decline, or cancel)""" - - action: Action - """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" - - content: dict[str, float | bool | list[str] | str] | None = None - """The form values submitted by the user (present when action is 'accept')""" - - @staticmethod - def from_dict(obj: Any) -> 'SessionUIHandlePendingElicitationParamsResult': - assert isinstance(obj, dict) - action = Action(obj.get("action")) - content = from_union([lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) - return SessionUIHandlePendingElicitationParamsResult(action, content) - - def to_dict(self) -> dict: - result: dict = {} - result["action"] = to_enum(Action, self.action) - if self.content is not None: - result["content"] = from_union([lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) - return result - - -@dataclass -class SessionUIHandlePendingElicitationParams: +class HandlePendingElicitationRequest: request_id: str """The unique request ID from the elicitation.requested event""" - result: SessionUIHandlePendingElicitationParamsResult - """The elicitation response (accept with form values, decline, or cancel)""" + result: UIElicitationResponse @staticmethod - def from_dict(obj: Any) -> 'SessionUIHandlePendingElicitationParams': + def from_dict(obj: Any) -> 'HandlePendingElicitationRequest': assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) - result = SessionUIHandlePendingElicitationParamsResult.from_dict(obj.get("result")) - return SessionUIHandlePendingElicitationParams(request_id, result) + result = UIElicitationResponse.from_dict(obj.get("result")) + return HandlePendingElicitationRequest(request_id, result) def to_dict(self) -> dict: result: dict = {} result["requestId"] = from_str(self.request_id) - result["result"] = to_class(SessionUIHandlePendingElicitationParamsResult, self.result) + result["result"] = to_class(UIElicitationResponse, self.result) return result - @dataclass -class SessionPermissionsHandlePendingPermissionRequestResult: +class PermissionRequestResult: success: bool """Whether the permission request was handled successfully""" @staticmethod - def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestResult': + def from_dict(obj: Any) -> 'PermissionRequestResult': assert isinstance(obj, dict) success = from_bool(obj.get("success")) - return SessionPermissionsHandlePendingPermissionRequestResult(success) + return PermissionRequestResult(success) def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) return result - class Kind(Enum): APPROVED = "approved" DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy" @@ -2524,9 +2323,8 @@ class Kind(Enum): 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" - @dataclass -class SessionPermissionsHandlePendingPermissionRequestParamsResult: +class PermissionDecision: kind: Kind """The permission request was approved @@ -2558,7 +2356,7 @@ class SessionPermissionsHandlePendingPermissionRequestParamsResult: """Whether to interrupt the current agent turn""" @staticmethod - def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestParamsResult': + def from_dict(obj: Any) -> 'PermissionDecision': assert isinstance(obj, dict) kind = Kind(obj.get("kind")) rules = from_union([lambda x: from_list(lambda x: x, x), from_none], obj.get("rules")) @@ -2566,7 +2364,7 @@ def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestPara message = from_union([from_str, from_none], obj.get("message")) path = from_union([from_str, from_none], obj.get("path")) interrupt = from_union([from_bool, from_none], obj.get("interrupt")) - return SessionPermissionsHandlePendingPermissionRequestParamsResult(kind, rules, feedback, message, path, interrupt) + return PermissionDecision(kind, rules, feedback, message, path, interrupt) def to_dict(self) -> dict: result: dict = {} @@ -2583,46 +2381,43 @@ def to_dict(self) -> dict: result["interrupt"] = from_union([from_bool, from_none], self.interrupt) return result - @dataclass -class SessionPermissionsHandlePendingPermissionRequestParams: +class PermissionDecisionRequest: request_id: str """Request ID of the pending permission request""" - result: SessionPermissionsHandlePendingPermissionRequestParamsResult + result: PermissionDecision @staticmethod - def from_dict(obj: Any) -> 'SessionPermissionsHandlePendingPermissionRequestParams': + def from_dict(obj: Any) -> 'PermissionDecisionRequest': assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) - result = SessionPermissionsHandlePendingPermissionRequestParamsResult.from_dict(obj.get("result")) - return SessionPermissionsHandlePendingPermissionRequestParams(request_id, result) + result = PermissionDecision.from_dict(obj.get("result")) + return PermissionDecisionRequest(request_id, result) def to_dict(self) -> dict: result: dict = {} result["requestId"] = from_str(self.request_id) - result["result"] = to_class(SessionPermissionsHandlePendingPermissionRequestParamsResult, self.result) + result["result"] = to_class(PermissionDecision, self.result) return result - @dataclass -class SessionLogResult: +class LogResult: event_id: UUID """The unique identifier of the emitted session event""" @staticmethod - def from_dict(obj: Any) -> 'SessionLogResult': + def from_dict(obj: Any) -> 'LogResult': assert isinstance(obj, dict) event_id = UUID(obj.get("eventId")) - return SessionLogResult(event_id) + return LogResult(event_id) def to_dict(self) -> dict: result: dict = {} result["eventId"] = str(self.event_id) return result - -class Level(Enum): +class SessionLogLevel(Enum): """Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". """ @@ -2630,30 +2425,26 @@ class Level(Enum): INFO = "info" WARNING = "warning" - @dataclass -class SessionLogParams: +class LogRequest: message: str """Human-readable message""" ephemeral: bool | None = None """When true, the message is transient and not persisted to the session event log on disk""" - level: Level | None = None - """Log severity level. Determines how the message is displayed in the timeline. Defaults to - "info". - """ + level: SessionLogLevel | None = None url: str | None = None """Optional URL the user can open in their browser for more details""" @staticmethod - def from_dict(obj: Any) -> 'SessionLogParams': + def from_dict(obj: Any) -> 'LogRequest': assert isinstance(obj, dict) message = from_str(obj.get("message")) ephemeral = from_union([from_bool, from_none], obj.get("ephemeral")) - level = from_union([Level, from_none], obj.get("level")) + level = from_union([SessionLogLevel, from_none], obj.get("level")) url = from_union([from_str, from_none], obj.get("url")) - return SessionLogParams(message, ephemeral, level, url) + return LogRequest(message, ephemeral, level, url) def to_dict(self) -> dict: result: dict = {} @@ -2661,47 +2452,45 @@ def to_dict(self) -> dict: if self.ephemeral is not None: result["ephemeral"] = from_union([from_bool, from_none], self.ephemeral) if self.level is not None: - result["level"] = from_union([lambda x: to_enum(Level, x), from_none], self.level) + result["level"] = from_union([lambda x: to_enum(SessionLogLevel, x), from_none], self.level) if self.url is not None: result["url"] = from_union([from_str, from_none], self.url) return result - @dataclass -class SessionShellExecResult: +class ShellExecResult: process_id: str """Unique identifier for tracking streamed output""" @staticmethod - def from_dict(obj: Any) -> 'SessionShellExecResult': + def from_dict(obj: Any) -> 'ShellExecResult': assert isinstance(obj, dict) process_id = from_str(obj.get("processId")) - return SessionShellExecResult(process_id) + return ShellExecResult(process_id) def to_dict(self) -> dict: result: dict = {} result["processId"] = from_str(self.process_id) return result - @dataclass -class SessionShellExecParams: +class ShellExecRequest: command: str """Shell command to execute""" cwd: str | None = None """Working directory (defaults to session working directory)""" - timeout: float | None = None + timeout: int | None = None """Timeout in milliseconds (default: 30000)""" @staticmethod - def from_dict(obj: Any) -> 'SessionShellExecParams': + def from_dict(obj: Any) -> 'ShellExecRequest': assert isinstance(obj, dict) command = from_str(obj.get("command")) cwd = from_union([from_str, from_none], obj.get("cwd")) - timeout = from_union([from_float, from_none], obj.get("timeout")) - return SessionShellExecParams(command, cwd, timeout) + timeout = from_union([from_int, from_none], obj.get("timeout")) + return ShellExecRequest(command, cwd, timeout) def to_dict(self) -> dict: result: dict = {} @@ -2709,177 +2498,167 @@ def to_dict(self) -> dict: if self.cwd is not None: result["cwd"] = from_union([from_str, from_none], self.cwd) if self.timeout is not None: - result["timeout"] = from_union([to_float, from_none], self.timeout) + result["timeout"] = from_union([from_int, from_none], self.timeout) return result - @dataclass -class SessionShellKillResult: +class ShellKillResult: killed: bool """Whether the signal was sent successfully""" @staticmethod - def from_dict(obj: Any) -> 'SessionShellKillResult': + def from_dict(obj: Any) -> 'ShellKillResult': assert isinstance(obj, dict) killed = from_bool(obj.get("killed")) - return SessionShellKillResult(killed) + return ShellKillResult(killed) def to_dict(self) -> dict: result: dict = {} result["killed"] = from_bool(self.killed) return result - -class Signal(Enum): +class ShellKillSignal(Enum): """Signal to send (default: SIGTERM)""" SIGINT = "SIGINT" SIGKILL = "SIGKILL" SIGTERM = "SIGTERM" - @dataclass -class SessionShellKillParams: +class ShellKillRequest: process_id: str """Process identifier returned by shell.exec""" - signal: Signal | None = None - """Signal to send (default: SIGTERM)""" + signal: ShellKillSignal | None = None @staticmethod - def from_dict(obj: Any) -> 'SessionShellKillParams': + def from_dict(obj: Any) -> 'ShellKillRequest': assert isinstance(obj, dict) process_id = from_str(obj.get("processId")) - signal = from_union([Signal, from_none], obj.get("signal")) - return SessionShellKillParams(process_id, signal) + signal = from_union([ShellKillSignal, from_none], obj.get("signal")) + return ShellKillRequest(process_id, signal) def to_dict(self) -> dict: result: dict = {} result["processId"] = from_str(self.process_id) if self.signal is not None: - result["signal"] = from_union([lambda x: to_enum(Signal, x), from_none], self.signal) + result["signal"] = from_union([lambda x: to_enum(ShellKillSignal, x), from_none], self.signal) return result - @dataclass -class ContextWindow: +class HistoryCompactContextWindow: """Post-compaction context window usage breakdown""" - current_tokens: float + current_tokens: int """Current total tokens in the context window (system + conversation + tool definitions)""" - messages_length: float + messages_length: int """Current number of messages in the conversation""" - token_limit: float + token_limit: int """Maximum token count for the model's context window""" - conversation_tokens: float | None = None + conversation_tokens: int | None = None """Token count from non-system messages (user, assistant, tool)""" - system_tokens: float | None = None + system_tokens: int | None = None """Token count from system message(s)""" - tool_definitions_tokens: float | None = None + tool_definitions_tokens: int | None = None """Token count from tool definitions""" @staticmethod - def from_dict(obj: Any) -> 'ContextWindow': + def from_dict(obj: Any) -> 'HistoryCompactContextWindow': assert isinstance(obj, dict) - current_tokens = from_float(obj.get("currentTokens")) - messages_length = from_float(obj.get("messagesLength")) - token_limit = from_float(obj.get("tokenLimit")) - conversation_tokens = from_union([from_float, from_none], obj.get("conversationTokens")) - system_tokens = from_union([from_float, from_none], obj.get("systemTokens")) - tool_definitions_tokens = from_union([from_float, from_none], obj.get("toolDefinitionsTokens")) - return ContextWindow(current_tokens, messages_length, token_limit, conversation_tokens, system_tokens, tool_definitions_tokens) + current_tokens = from_int(obj.get("currentTokens")) + messages_length = from_int(obj.get("messagesLength")) + token_limit = from_int(obj.get("tokenLimit")) + conversation_tokens = from_union([from_int, from_none], obj.get("conversationTokens")) + system_tokens = from_union([from_int, from_none], obj.get("systemTokens")) + tool_definitions_tokens = from_union([from_int, from_none], obj.get("toolDefinitionsTokens")) + return HistoryCompactContextWindow(current_tokens, messages_length, token_limit, conversation_tokens, system_tokens, tool_definitions_tokens) def to_dict(self) -> dict: result: dict = {} - result["currentTokens"] = to_float(self.current_tokens) - result["messagesLength"] = to_float(self.messages_length) - result["tokenLimit"] = to_float(self.token_limit) + result["currentTokens"] = from_int(self.current_tokens) + result["messagesLength"] = from_int(self.messages_length) + result["tokenLimit"] = from_int(self.token_limit) if self.conversation_tokens is not None: - result["conversationTokens"] = from_union([to_float, from_none], self.conversation_tokens) + result["conversationTokens"] = from_union([from_int, from_none], self.conversation_tokens) if self.system_tokens is not None: - result["systemTokens"] = from_union([to_float, from_none], self.system_tokens) + result["systemTokens"] = from_union([from_int, from_none], self.system_tokens) if self.tool_definitions_tokens is not None: - result["toolDefinitionsTokens"] = from_union([to_float, from_none], self.tool_definitions_tokens) + result["toolDefinitionsTokens"] = from_union([from_int, from_none], self.tool_definitions_tokens) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionHistoryCompactResult: - messages_removed: float +class HistoryCompact: + messages_removed: int """Number of messages removed during compaction""" success: bool """Whether compaction completed successfully""" - tokens_removed: float + tokens_removed: int """Number of tokens freed by compaction""" - context_window: ContextWindow | None = None - """Post-compaction context window usage breakdown""" + context_window: HistoryCompactContextWindow | None = None @staticmethod - def from_dict(obj: Any) -> 'SessionHistoryCompactResult': + def from_dict(obj: Any) -> 'HistoryCompact': assert isinstance(obj, dict) - messages_removed = from_float(obj.get("messagesRemoved")) + messages_removed = from_int(obj.get("messagesRemoved")) success = from_bool(obj.get("success")) - tokens_removed = from_float(obj.get("tokensRemoved")) - context_window = from_union([ContextWindow.from_dict, from_none], obj.get("contextWindow")) - return SessionHistoryCompactResult(messages_removed, success, tokens_removed, context_window) + tokens_removed = from_int(obj.get("tokensRemoved")) + context_window = from_union([HistoryCompactContextWindow.from_dict, from_none], obj.get("contextWindow")) + return HistoryCompact(messages_removed, success, tokens_removed, context_window) def to_dict(self) -> dict: result: dict = {} - result["messagesRemoved"] = to_float(self.messages_removed) + result["messagesRemoved"] = from_int(self.messages_removed) result["success"] = from_bool(self.success) - result["tokensRemoved"] = to_float(self.tokens_removed) + result["tokensRemoved"] = from_int(self.tokens_removed) if self.context_window is not None: - result["contextWindow"] = from_union([lambda x: to_class(ContextWindow, x), from_none], self.context_window) + result["contextWindow"] = from_union([lambda x: to_class(HistoryCompactContextWindow, x), from_none], self.context_window) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionHistoryTruncateResult: - events_removed: float +class HistoryTruncateResult: + events_removed: int """Number of events that were removed""" @staticmethod - def from_dict(obj: Any) -> 'SessionHistoryTruncateResult': + def from_dict(obj: Any) -> 'HistoryTruncateResult': assert isinstance(obj, dict) - events_removed = from_float(obj.get("eventsRemoved")) - return SessionHistoryTruncateResult(events_removed) + events_removed = from_int(obj.get("eventsRemoved")) + return HistoryTruncateResult(events_removed) def to_dict(self) -> dict: result: dict = {} - result["eventsRemoved"] = to_float(self.events_removed) + result["eventsRemoved"] = from_int(self.events_removed) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionHistoryTruncateParams: +class HistoryTruncateRequest: event_id: str """Event ID to truncate to. This event and all events after it are removed from the session.""" @staticmethod - def from_dict(obj: Any) -> 'SessionHistoryTruncateParams': + def from_dict(obj: Any) -> 'HistoryTruncateRequest': assert isinstance(obj, dict) event_id = from_str(obj.get("eventId")) - return SessionHistoryTruncateParams(event_id) + return HistoryTruncateRequest(event_id) def to_dict(self) -> dict: result: dict = {} result["eventId"] = from_str(self.event_id) return result - @dataclass -class CodeChanges: +class UsageMetricsCodeChanges: """Aggregated code change metrics""" files_modified_count: int @@ -2892,12 +2671,12 @@ class CodeChanges: """Total lines of code removed""" @staticmethod - def from_dict(obj: Any) -> 'CodeChanges': + def from_dict(obj: Any) -> 'UsageMetricsCodeChanges': assert isinstance(obj, dict) files_modified_count = from_int(obj.get("filesModifiedCount")) lines_added = from_int(obj.get("linesAdded")) lines_removed = from_int(obj.get("linesRemoved")) - return CodeChanges(files_modified_count, lines_added, lines_removed) + return UsageMetricsCodeChanges(files_modified_count, lines_added, lines_removed) def to_dict(self) -> dict: result: dict = {} @@ -2906,9 +2685,8 @@ def to_dict(self) -> dict: result["linesRemoved"] = from_int(self.lines_removed) return result - @dataclass -class Requests: +class UsageMetricsModelMetricRequests: """Request count and cost metrics for this model""" cost: float @@ -2918,11 +2696,11 @@ class Requests: """Number of API requests made with this model""" @staticmethod - def from_dict(obj: Any) -> 'Requests': + def from_dict(obj: Any) -> 'UsageMetricsModelMetricRequests': assert isinstance(obj, dict) cost = from_float(obj.get("cost")) count = from_int(obj.get("count")) - return Requests(cost, count) + return UsageMetricsModelMetricRequests(cost, count) def to_dict(self) -> dict: result: dict = {} @@ -2930,9 +2708,8 @@ def to_dict(self) -> dict: result["count"] = from_int(self.count) return result - @dataclass -class Usage: +class UsageMetricsModelMetricUsage: """Token usage metrics for this model""" cache_read_tokens: int @@ -2947,14 +2724,18 @@ class Usage: output_tokens: int """Total output tokens produced""" + reasoning_tokens: int | None = None + """Total output tokens used for reasoning""" + @staticmethod - def from_dict(obj: Any) -> 'Usage': + def from_dict(obj: Any) -> 'UsageMetricsModelMetricUsage': assert isinstance(obj, dict) cache_read_tokens = from_int(obj.get("cacheReadTokens")) cache_write_tokens = from_int(obj.get("cacheWriteTokens")) input_tokens = from_int(obj.get("inputTokens")) output_tokens = from_int(obj.get("outputTokens")) - return Usage(cache_read_tokens, cache_write_tokens, input_tokens, output_tokens) + reasoning_tokens = from_union([from_int, from_none], obj.get("reasoningTokens")) + return UsageMetricsModelMetricUsage(cache_read_tokens, cache_write_tokens, input_tokens, output_tokens, reasoning_tokens) def to_dict(self) -> dict: result: dict = {} @@ -2962,44 +2743,39 @@ def to_dict(self) -> dict: result["cacheWriteTokens"] = from_int(self.cache_write_tokens) result["inputTokens"] = from_int(self.input_tokens) result["outputTokens"] = from_int(self.output_tokens) + if self.reasoning_tokens is not None: + result["reasoningTokens"] = from_union([from_int, from_none], self.reasoning_tokens) return result - @dataclass -class ModelMetric: - requests: Requests - """Request count and cost metrics for this model""" - - usage: Usage - """Token usage metrics for this model""" +class UsageMetricsModelMetric: + requests: UsageMetricsModelMetricRequests + usage: UsageMetricsModelMetricUsage @staticmethod - def from_dict(obj: Any) -> 'ModelMetric': + def from_dict(obj: Any) -> 'UsageMetricsModelMetric': assert isinstance(obj, dict) - requests = Requests.from_dict(obj.get("requests")) - usage = Usage.from_dict(obj.get("usage")) - return ModelMetric(requests, usage) + requests = UsageMetricsModelMetricRequests.from_dict(obj.get("requests")) + usage = UsageMetricsModelMetricUsage.from_dict(obj.get("usage")) + return UsageMetricsModelMetric(requests, usage) def to_dict(self) -> dict: result: dict = {} - result["requests"] = to_class(Requests, self.requests) - result["usage"] = to_class(Usage, self.usage) + result["requests"] = to_class(UsageMetricsModelMetricRequests, self.requests) + result["usage"] = to_class(UsageMetricsModelMetricUsage, self.usage) return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionUsageGetMetricsResult: - code_changes: CodeChanges - """Aggregated code change metrics""" - +class UsageMetrics: + code_changes: UsageMetricsCodeChanges last_call_input_tokens: int """Input tokens from the most recent main-agent API call""" last_call_output_tokens: int """Output tokens from the most recent main-agent API call""" - model_metrics: dict[str, ModelMetric] + model_metrics: dict[str, UsageMetricsModelMetric] """Per-model token and request metrics, keyed by model identifier""" session_start_time: int @@ -3019,25 +2795,25 @@ class SessionUsageGetMetricsResult: """Currently active model identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionUsageGetMetricsResult': + def from_dict(obj: Any) -> 'UsageMetrics': assert isinstance(obj, dict) - code_changes = CodeChanges.from_dict(obj.get("codeChanges")) + code_changes = UsageMetricsCodeChanges.from_dict(obj.get("codeChanges")) last_call_input_tokens = from_int(obj.get("lastCallInputTokens")) last_call_output_tokens = from_int(obj.get("lastCallOutputTokens")) - model_metrics = from_dict(ModelMetric.from_dict, obj.get("modelMetrics")) + model_metrics = from_dict(UsageMetricsModelMetric.from_dict, obj.get("modelMetrics")) session_start_time = from_int(obj.get("sessionStartTime")) total_api_duration_ms = from_float(obj.get("totalApiDurationMs")) total_premium_request_cost = from_float(obj.get("totalPremiumRequestCost")) total_user_requests = from_int(obj.get("totalUserRequests")) current_model = from_union([from_str, from_none], obj.get("currentModel")) - return SessionUsageGetMetricsResult(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model) + return UsageMetrics(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model) def to_dict(self) -> dict: result: dict = {} - result["codeChanges"] = to_class(CodeChanges, self.code_changes) + result["codeChanges"] = to_class(UsageMetricsCodeChanges, self.code_changes) result["lastCallInputTokens"] = from_int(self.last_call_input_tokens) result["lastCallOutputTokens"] = from_int(self.last_call_output_tokens) - result["modelMetrics"] = from_dict(lambda x: to_class(ModelMetric, x), self.model_metrics) + result["modelMetrics"] = from_dict(lambda x: to_class(UsageMetricsModelMetric, x), self.model_metrics) result["sessionStartTime"] = from_int(self.session_start_time) result["totalApiDurationMs"] = to_float(self.total_api_duration_ms) result["totalPremiumRequestCost"] = to_float(self.total_premium_request_cost) @@ -3046,7 +2822,6 @@ def to_dict(self) -> dict: result["currentModel"] = from_union([from_str, from_none], self.current_model) return result - @dataclass class SessionFSReadFileResult: content: str @@ -3063,9 +2838,8 @@ def to_dict(self) -> dict: result["content"] = from_str(self.content) return result - @dataclass -class SessionFSReadFileParams: +class SessionFSReadFileRequest: path: str """Path using SessionFs conventions""" @@ -3073,11 +2847,11 @@ class SessionFSReadFileParams: """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReadFileParams': + def from_dict(obj: Any) -> 'SessionFSReadFileRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - return SessionFSReadFileParams(path, session_id) + return SessionFSReadFileRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} @@ -3085,9 +2859,8 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - @dataclass -class SessionFSWriteFileParams: +class SessionFSWriteFileRequest: content: str """Content to write""" @@ -3097,17 +2870,17 @@ class SessionFSWriteFileParams: session_id: str """Target session identifier""" - mode: float | None = None + mode: int | None = None """Optional POSIX-style mode for newly created files""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSWriteFileParams': + def from_dict(obj: Any) -> 'SessionFSWriteFileRequest': assert isinstance(obj, dict) content = from_str(obj.get("content")) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - mode = from_union([from_float, from_none], obj.get("mode")) - return SessionFSWriteFileParams(content, path, session_id, mode) + mode = from_union([from_int, from_none], obj.get("mode")) + return SessionFSWriteFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} @@ -3115,12 +2888,11 @@ def to_dict(self) -> dict: result["path"] = from_str(self.path) result["sessionId"] = from_str(self.session_id) if self.mode is not None: - result["mode"] = from_union([to_float, from_none], self.mode) + result["mode"] = from_union([from_int, from_none], self.mode) return result - @dataclass -class SessionFSAppendFileParams: +class SessionFSAppendFileRequest: content: str """Content to append""" @@ -3130,17 +2902,17 @@ class SessionFSAppendFileParams: session_id: str """Target session identifier""" - mode: float | None = None + mode: int | None = None """Optional POSIX-style mode for newly created files""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSAppendFileParams': + def from_dict(obj: Any) -> 'SessionFSAppendFileRequest': assert isinstance(obj, dict) content = from_str(obj.get("content")) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - mode = from_union([from_float, from_none], obj.get("mode")) - return SessionFSAppendFileParams(content, path, session_id, mode) + mode = from_union([from_int, from_none], obj.get("mode")) + return SessionFSAppendFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} @@ -3148,10 +2920,9 @@ def to_dict(self) -> dict: result["path"] = from_str(self.path) result["sessionId"] = from_str(self.session_id) if self.mode is not None: - result["mode"] = from_union([to_float, from_none], self.mode) + result["mode"] = from_union([from_int, from_none], self.mode) return result - @dataclass class SessionFSExistsResult: exists: bool @@ -3168,9 +2939,8 @@ def to_dict(self) -> dict: result["exists"] = from_bool(self.exists) return result - @dataclass -class SessionFSExistsParams: +class SessionFSExistsRequest: path: str """Path using SessionFs conventions""" @@ -3178,11 +2948,11 @@ class SessionFSExistsParams: """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSExistsParams': + def from_dict(obj: Any) -> 'SessionFSExistsRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - return SessionFSExistsParams(path, session_id) + return SessionFSExistsRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} @@ -3190,10 +2960,9 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - @dataclass class SessionFSStatResult: - birthtime: str + birthtime: datetime """ISO 8601 timestamp of creation""" is_directory: bool @@ -3202,34 +2971,33 @@ class SessionFSStatResult: is_file: bool """Whether the path is a file""" - mtime: str + mtime: datetime """ISO 8601 timestamp of last modification""" - size: float + size: int """File size in bytes""" @staticmethod def from_dict(obj: Any) -> 'SessionFSStatResult': assert isinstance(obj, dict) - birthtime = from_str(obj.get("birthtime")) + birthtime = from_datetime(obj.get("birthtime")) is_directory = from_bool(obj.get("isDirectory")) is_file = from_bool(obj.get("isFile")) - mtime = from_str(obj.get("mtime")) - size = from_float(obj.get("size")) + mtime = from_datetime(obj.get("mtime")) + size = from_int(obj.get("size")) return SessionFSStatResult(birthtime, is_directory, is_file, mtime, size) def to_dict(self) -> dict: result: dict = {} - result["birthtime"] = from_str(self.birthtime) + result["birthtime"] = self.birthtime.isoformat() result["isDirectory"] = from_bool(self.is_directory) result["isFile"] = from_bool(self.is_file) - result["mtime"] = from_str(self.mtime) - result["size"] = to_float(self.size) + result["mtime"] = self.mtime.isoformat() + result["size"] = from_int(self.size) return result - @dataclass -class SessionFSStatParams: +class SessionFSStatRequest: path: str """Path using SessionFs conventions""" @@ -3237,11 +3005,11 @@ class SessionFSStatParams: """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSStatParams': + def from_dict(obj: Any) -> 'SessionFSStatRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - return SessionFSStatParams(path, session_id) + return SessionFSStatRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} @@ -3249,41 +3017,39 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - @dataclass -class SessionFSMkdirParams: +class SessionFSMkdirRequest: path: str """Path using SessionFs conventions""" session_id: str """Target session identifier""" - mode: float | None = None + mode: int | None = None """Optional POSIX-style mode for newly created directories""" recursive: bool | None = None """Create parent directories as needed""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSMkdirParams': + def from_dict(obj: Any) -> 'SessionFSMkdirRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - mode = from_union([from_float, from_none], obj.get("mode")) + mode = from_union([from_int, from_none], obj.get("mode")) recursive = from_union([from_bool, from_none], obj.get("recursive")) - return SessionFSMkdirParams(path, session_id, mode, recursive) + return SessionFSMkdirRequest(path, session_id, mode, recursive) def to_dict(self) -> dict: result: dict = {} result["path"] = from_str(self.path) result["sessionId"] = from_str(self.session_id) if self.mode is not None: - result["mode"] = from_union([to_float, from_none], self.mode) + result["mode"] = from_union([from_int, from_none], self.mode) if self.recursive is not None: result["recursive"] = from_union([from_bool, from_none], self.recursive) return result - @dataclass class SessionFSReaddirResult: entries: list[str] @@ -3300,9 +3066,8 @@ def to_dict(self) -> dict: result["entries"] = from_list(from_str, self.entries) return result - @dataclass -class SessionFSReaddirParams: +class SessionFSReaddirRequest: path: str """Path using SessionFs conventions""" @@ -3310,11 +3075,11 @@ class SessionFSReaddirParams: """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReaddirParams': + def from_dict(obj: Any) -> 'SessionFSReaddirRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - return SessionFSReaddirParams(path, session_id) + return SessionFSReaddirRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} @@ -3322,55 +3087,50 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - -class EntryType(Enum): +class SessionFSReaddirWithTypesEntryType(Enum): """Entry type""" DIRECTORY = "directory" FILE = "file" - @dataclass -class Entry: +class SessionFSReaddirWithTypesEntry: name: str """Entry name""" - type: EntryType - """Entry type""" + type: SessionFSReaddirWithTypesEntryType @staticmethod - def from_dict(obj: Any) -> 'Entry': + def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry': assert isinstance(obj, dict) name = from_str(obj.get("name")) - type = EntryType(obj.get("type")) - return Entry(name, type) + type = SessionFSReaddirWithTypesEntryType(obj.get("type")) + return SessionFSReaddirWithTypesEntry(name, type) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) - result["type"] = to_enum(EntryType, self.type) + result["type"] = to_enum(SessionFSReaddirWithTypesEntryType, self.type) return result - @dataclass class SessionFSReaddirWithTypesResult: - entries: list[Entry] + entries: list[SessionFSReaddirWithTypesEntry] """Directory entries with type information""" @staticmethod def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesResult': assert isinstance(obj, dict) - entries = from_list(Entry.from_dict, obj.get("entries")) + entries = from_list(SessionFSReaddirWithTypesEntry.from_dict, obj.get("entries")) return SessionFSReaddirWithTypesResult(entries) def to_dict(self) -> dict: result: dict = {} - result["entries"] = from_list(lambda x: to_class(Entry, x), self.entries) + result["entries"] = from_list(lambda x: to_class(SessionFSReaddirWithTypesEntry, x), self.entries) return result - @dataclass -class SessionFSReaddirWithTypesParams: +class SessionFSReaddirWithTypesRequest: path: str """Path using SessionFs conventions""" @@ -3378,11 +3138,11 @@ class SessionFSReaddirWithTypesParams: """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesParams': + def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) - return SessionFSReaddirWithTypesParams(path, session_id) + return SessionFSReaddirWithTypesRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} @@ -3390,9 +3150,8 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - @dataclass -class SessionFSRmParams: +class SessionFSRmRequest: path: str """Path using SessionFs conventions""" @@ -3406,13 +3165,13 @@ class SessionFSRmParams: """Remove directories and their contents recursively""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSRmParams': + def from_dict(obj: Any) -> 'SessionFSRmRequest': assert isinstance(obj, dict) path = from_str(obj.get("path")) session_id = from_str(obj.get("sessionId")) force = from_union([from_bool, from_none], obj.get("force")) recursive = from_union([from_bool, from_none], obj.get("recursive")) - return SessionFSRmParams(path, session_id, force, recursive) + return SessionFSRmRequest(path, session_id, force, recursive) def to_dict(self) -> dict: result: dict = {} @@ -3424,9 +3183,8 @@ def to_dict(self) -> dict: result["recursive"] = from_union([from_bool, from_none], self.recursive) return result - @dataclass -class SessionFSRenameParams: +class SessionFSRenameRequest: dest: str """Destination path using SessionFs conventions""" @@ -3437,12 +3195,12 @@ class SessionFSRenameParams: """Source path using SessionFs conventions""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSRenameParams': + def from_dict(obj: Any) -> 'SessionFSRenameRequest': assert isinstance(obj, dict) dest = from_str(obj.get("dest")) session_id = from_str(obj.get("sessionId")) src = from_str(obj.get("src")) - return SessionFSRenameParams(dest, session_id, src) + return SessionFSRenameRequest(dest, session_id, src) def to_dict(self) -> dict: result: dict = {} @@ -3451,749 +3209,557 @@ def to_dict(self) -> dict: result["src"] = from_str(self.src) return result - def ping_result_from_dict(s: Any) -> PingResult: return PingResult.from_dict(s) - def ping_result_to_dict(x: PingResult) -> Any: return to_class(PingResult, x) +def ping_request_from_dict(s: Any) -> PingRequest: + return PingRequest.from_dict(s) -def ping_params_from_dict(s: Any) -> PingParams: - return PingParams.from_dict(s) - - -def ping_params_to_dict(x: PingParams) -> Any: - return to_class(PingParams, x) - - -def models_list_result_from_dict(s: Any) -> ModelsListResult: - return ModelsListResult.from_dict(s) - - -def models_list_result_to_dict(x: ModelsListResult) -> Any: - return to_class(ModelsListResult, x) - - -def tools_list_result_from_dict(s: Any) -> ToolsListResult: - return ToolsListResult.from_dict(s) - - -def tools_list_result_to_dict(x: ToolsListResult) -> Any: - return to_class(ToolsListResult, x) - - -def tools_list_params_from_dict(s: Any) -> ToolsListParams: - return ToolsListParams.from_dict(s) - - -def tools_list_params_to_dict(x: ToolsListParams) -> Any: - return to_class(ToolsListParams, x) - +def ping_request_to_dict(x: PingRequest) -> Any: + return to_class(PingRequest, x) -def account_get_quota_result_from_dict(s: Any) -> AccountGetQuotaResult: - return AccountGetQuotaResult.from_dict(s) +def model_list_from_dict(s: Any) -> ModelList: + return ModelList.from_dict(s) +def model_list_to_dict(x: ModelList) -> Any: + return to_class(ModelList, x) -def account_get_quota_result_to_dict(x: AccountGetQuotaResult) -> Any: - return to_class(AccountGetQuotaResult, x) +def tool_list_from_dict(s: Any) -> ToolList: + return ToolList.from_dict(s) +def tool_list_to_dict(x: ToolList) -> Any: + return to_class(ToolList, x) -def mcp_config_list_result_from_dict(s: Any) -> MCPConfigListResult: - return MCPConfigListResult.from_dict(s) +def tools_list_request_from_dict(s: Any) -> ToolsListRequest: + return ToolsListRequest.from_dict(s) +def tools_list_request_to_dict(x: ToolsListRequest) -> Any: + return to_class(ToolsListRequest, x) -def mcp_config_list_result_to_dict(x: MCPConfigListResult) -> Any: - return to_class(MCPConfigListResult, x) +def account_quota_from_dict(s: Any) -> AccountQuota: + return AccountQuota.from_dict(s) +def account_quota_to_dict(x: AccountQuota) -> Any: + return to_class(AccountQuota, x) -def mcp_config_add_params_from_dict(s: Any) -> MCPConfigAddParams: - return MCPConfigAddParams.from_dict(s) +def mcp_config_list_from_dict(s: Any) -> MCPConfigList: + return MCPConfigList.from_dict(s) +def mcp_config_list_to_dict(x: MCPConfigList) -> Any: + return to_class(MCPConfigList, x) -def mcp_config_add_params_to_dict(x: MCPConfigAddParams) -> Any: - return to_class(MCPConfigAddParams, x) +def mcp_config_add_request_from_dict(s: Any) -> MCPConfigAddRequest: + return MCPConfigAddRequest.from_dict(s) +def mcp_config_add_request_to_dict(x: MCPConfigAddRequest) -> Any: + return to_class(MCPConfigAddRequest, x) -def mcp_config_update_params_from_dict(s: Any) -> MCPConfigUpdateParams: - return MCPConfigUpdateParams.from_dict(s) +def mcp_config_update_request_from_dict(s: Any) -> MCPConfigUpdateRequest: + return MCPConfigUpdateRequest.from_dict(s) +def mcp_config_update_request_to_dict(x: MCPConfigUpdateRequest) -> Any: + return to_class(MCPConfigUpdateRequest, x) -def mcp_config_update_params_to_dict(x: MCPConfigUpdateParams) -> Any: - return to_class(MCPConfigUpdateParams, x) - - -def mcp_config_remove_params_from_dict(s: Any) -> MCPConfigRemoveParams: - return MCPConfigRemoveParams.from_dict(s) - - -def mcp_config_remove_params_to_dict(x: MCPConfigRemoveParams) -> Any: - return to_class(MCPConfigRemoveParams, x) +def mcp_config_remove_request_from_dict(s: Any) -> MCPConfigRemoveRequest: + return MCPConfigRemoveRequest.from_dict(s) +def mcp_config_remove_request_to_dict(x: MCPConfigRemoveRequest) -> Any: + return to_class(MCPConfigRemoveRequest, x) def mcp_discover_result_from_dict(s: Any) -> MCPDiscoverResult: return MCPDiscoverResult.from_dict(s) - def mcp_discover_result_to_dict(x: MCPDiscoverResult) -> Any: return to_class(MCPDiscoverResult, x) +def mcp_discover_request_from_dict(s: Any) -> MCPDiscoverRequest: + return MCPDiscoverRequest.from_dict(s) -def mcp_discover_params_from_dict(s: Any) -> MCPDiscoverParams: - return MCPDiscoverParams.from_dict(s) - - -def mcp_discover_params_to_dict(x: MCPDiscoverParams) -> Any: - return to_class(MCPDiscoverParams, x) - +def mcp_discover_request_to_dict(x: MCPDiscoverRequest) -> Any: + return to_class(MCPDiscoverRequest, x) def session_fs_set_provider_result_from_dict(s: Any) -> SessionFSSetProviderResult: return SessionFSSetProviderResult.from_dict(s) - def session_fs_set_provider_result_to_dict(x: SessionFSSetProviderResult) -> Any: return to_class(SessionFSSetProviderResult, x) +def session_fs_set_provider_request_from_dict(s: Any) -> SessionFSSetProviderRequest: + return SessionFSSetProviderRequest.from_dict(s) -def session_fs_set_provider_params_from_dict(s: Any) -> SessionFSSetProviderParams: - return SessionFSSetProviderParams.from_dict(s) - - -def session_fs_set_provider_params_to_dict(x: SessionFSSetProviderParams) -> Any: - return to_class(SessionFSSetProviderParams, x) - +def session_fs_set_provider_request_to_dict(x: SessionFSSetProviderRequest) -> Any: + return to_class(SessionFSSetProviderRequest, x) def sessions_fork_result_from_dict(s: Any) -> SessionsForkResult: return SessionsForkResult.from_dict(s) - def sessions_fork_result_to_dict(x: SessionsForkResult) -> Any: return to_class(SessionsForkResult, x) +def sessions_fork_request_from_dict(s: Any) -> SessionsForkRequest: + return SessionsForkRequest.from_dict(s) -def sessions_fork_params_from_dict(s: Any) -> SessionsForkParams: - return SessionsForkParams.from_dict(s) - - -def sessions_fork_params_to_dict(x: SessionsForkParams) -> Any: - return to_class(SessionsForkParams, x) - - -def session_model_get_current_result_from_dict(s: Any) -> SessionModelGetCurrentResult: - return SessionModelGetCurrentResult.from_dict(s) - - -def session_model_get_current_result_to_dict(x: SessionModelGetCurrentResult) -> Any: - return to_class(SessionModelGetCurrentResult, x) - - -def session_model_switch_to_result_from_dict(s: Any) -> SessionModelSwitchToResult: - return SessionModelSwitchToResult.from_dict(s) - - -def session_model_switch_to_result_to_dict(x: SessionModelSwitchToResult) -> Any: - return to_class(SessionModelSwitchToResult, x) - - -def session_model_switch_to_params_from_dict(s: Any) -> SessionModelSwitchToParams: - return SessionModelSwitchToParams.from_dict(s) - - -def session_model_switch_to_params_to_dict(x: SessionModelSwitchToParams) -> Any: - return to_class(SessionModelSwitchToParams, x) - - -def session_mode_get_result_from_dict(s: Any) -> SessionModeGetResult: - return SessionModeGetResult.from_dict(s) - - -def session_mode_get_result_to_dict(x: SessionModeGetResult) -> Any: - return to_class(SessionModeGetResult, x) - - -def session_mode_set_result_from_dict(s: Any) -> SessionModeSetResult: - return SessionModeSetResult.from_dict(s) - - -def session_mode_set_result_to_dict(x: SessionModeSetResult) -> Any: - return to_class(SessionModeSetResult, x) - - -def session_mode_set_params_from_dict(s: Any) -> SessionModeSetParams: - return SessionModeSetParams.from_dict(s) - - -def session_mode_set_params_to_dict(x: SessionModeSetParams) -> Any: - return to_class(SessionModeSetParams, x) - - -def session_plan_read_result_from_dict(s: Any) -> SessionPlanReadResult: - return SessionPlanReadResult.from_dict(s) - - -def session_plan_read_result_to_dict(x: SessionPlanReadResult) -> Any: - return to_class(SessionPlanReadResult, x) - - -def session_plan_update_result_from_dict(s: Any) -> SessionPlanUpdateResult: - return SessionPlanUpdateResult.from_dict(s) - - -def session_plan_update_result_to_dict(x: SessionPlanUpdateResult) -> Any: - return to_class(SessionPlanUpdateResult, x) - - -def session_plan_update_params_from_dict(s: Any) -> SessionPlanUpdateParams: - return SessionPlanUpdateParams.from_dict(s) - - -def session_plan_update_params_to_dict(x: SessionPlanUpdateParams) -> Any: - return to_class(SessionPlanUpdateParams, x) - - -def session_plan_delete_result_from_dict(s: Any) -> SessionPlanDeleteResult: - return SessionPlanDeleteResult.from_dict(s) - - -def session_plan_delete_result_to_dict(x: SessionPlanDeleteResult) -> Any: - return to_class(SessionPlanDeleteResult, x) - - -def session_workspace_list_files_result_from_dict(s: Any) -> SessionWorkspaceListFilesResult: - return SessionWorkspaceListFilesResult.from_dict(s) +def sessions_fork_request_to_dict(x: SessionsForkRequest) -> Any: + return to_class(SessionsForkRequest, x) +def model_current_from_dict(s: Any) -> ModelCurrent: + return ModelCurrent.from_dict(s) -def session_workspace_list_files_result_to_dict(x: SessionWorkspaceListFilesResult) -> Any: - return to_class(SessionWorkspaceListFilesResult, x) +def model_current_to_dict(x: ModelCurrent) -> Any: + return to_class(ModelCurrent, x) +def model_switch_to_result_from_dict(s: Any) -> ModelSwitchToResult: + return ModelSwitchToResult.from_dict(s) -def session_workspace_read_file_result_from_dict(s: Any) -> SessionWorkspaceReadFileResult: - return SessionWorkspaceReadFileResult.from_dict(s) +def model_switch_to_result_to_dict(x: ModelSwitchToResult) -> Any: + return to_class(ModelSwitchToResult, x) +def model_switch_to_request_from_dict(s: Any) -> ModelSwitchToRequest: + return ModelSwitchToRequest.from_dict(s) -def session_workspace_read_file_result_to_dict(x: SessionWorkspaceReadFileResult) -> Any: - return to_class(SessionWorkspaceReadFileResult, x) +def model_switch_to_request_to_dict(x: ModelSwitchToRequest) -> Any: + return to_class(ModelSwitchToRequest, x) +def session_mode_from_dict(s: Any) -> SessionMode: + return SessionMode(s) -def session_workspace_read_file_params_from_dict(s: Any) -> SessionWorkspaceReadFileParams: - return SessionWorkspaceReadFileParams.from_dict(s) +def session_mode_to_dict(x: SessionMode) -> Any: + return to_enum(SessionMode, x) +def mode_set_request_from_dict(s: Any) -> ModeSetRequest: + return ModeSetRequest.from_dict(s) -def session_workspace_read_file_params_to_dict(x: SessionWorkspaceReadFileParams) -> Any: - return to_class(SessionWorkspaceReadFileParams, x) +def mode_set_request_to_dict(x: ModeSetRequest) -> Any: + return to_class(ModeSetRequest, x) +def plan_from_dict(s: Any) -> Plan: + return Plan.from_dict(s) -def session_workspace_create_file_result_from_dict(s: Any) -> SessionWorkspaceCreateFileResult: - return SessionWorkspaceCreateFileResult.from_dict(s) +def plan_to_dict(x: Plan) -> Any: + return to_class(Plan, x) +def plan_update_result_from_dict(s: Any) -> PlanUpdateResult: + return PlanUpdateResult.from_dict(s) -def session_workspace_create_file_result_to_dict(x: SessionWorkspaceCreateFileResult) -> Any: - return to_class(SessionWorkspaceCreateFileResult, x) +def plan_update_result_to_dict(x: PlanUpdateResult) -> Any: + return to_class(PlanUpdateResult, x) +def plan_update_request_from_dict(s: Any) -> PlanUpdateRequest: + return PlanUpdateRequest.from_dict(s) -def session_workspace_create_file_params_from_dict(s: Any) -> SessionWorkspaceCreateFileParams: - return SessionWorkspaceCreateFileParams.from_dict(s) +def plan_update_request_to_dict(x: PlanUpdateRequest) -> Any: + return to_class(PlanUpdateRequest, x) +def plan_delete_from_dict(s: Any) -> PlanDelete: + return PlanDelete.from_dict(s) -def session_workspace_create_file_params_to_dict(x: SessionWorkspaceCreateFileParams) -> Any: - return to_class(SessionWorkspaceCreateFileParams, x) +def plan_delete_to_dict(x: PlanDelete) -> Any: + return to_class(PlanDelete, x) +def workspace_files_from_dict(s: Any) -> WorkspaceFiles: + return WorkspaceFiles.from_dict(s) -def session_fleet_start_result_from_dict(s: Any) -> SessionFleetStartResult: - return SessionFleetStartResult.from_dict(s) +def workspace_files_to_dict(x: WorkspaceFiles) -> Any: + return to_class(WorkspaceFiles, x) +def workspace_read_file_result_from_dict(s: Any) -> WorkspaceReadFileResult: + return WorkspaceReadFileResult.from_dict(s) -def session_fleet_start_result_to_dict(x: SessionFleetStartResult) -> Any: - return to_class(SessionFleetStartResult, x) +def workspace_read_file_result_to_dict(x: WorkspaceReadFileResult) -> Any: + return to_class(WorkspaceReadFileResult, x) +def workspace_read_file_request_from_dict(s: Any) -> WorkspaceReadFileRequest: + return WorkspaceReadFileRequest.from_dict(s) -def session_fleet_start_params_from_dict(s: Any) -> SessionFleetStartParams: - return SessionFleetStartParams.from_dict(s) +def workspace_read_file_request_to_dict(x: WorkspaceReadFileRequest) -> Any: + return to_class(WorkspaceReadFileRequest, x) +def workspace_create_file_result_from_dict(s: Any) -> WorkspaceCreateFileResult: + return WorkspaceCreateFileResult.from_dict(s) -def session_fleet_start_params_to_dict(x: SessionFleetStartParams) -> Any: - return to_class(SessionFleetStartParams, x) +def workspace_create_file_result_to_dict(x: WorkspaceCreateFileResult) -> Any: + return to_class(WorkspaceCreateFileResult, x) +def workspace_create_file_request_from_dict(s: Any) -> WorkspaceCreateFileRequest: + return WorkspaceCreateFileRequest.from_dict(s) -def session_agent_list_result_from_dict(s: Any) -> SessionAgentListResult: - return SessionAgentListResult.from_dict(s) +def workspace_create_file_request_to_dict(x: WorkspaceCreateFileRequest) -> Any: + return to_class(WorkspaceCreateFileRequest, x) +def fleet_start_result_from_dict(s: Any) -> FleetStartResult: + return FleetStartResult.from_dict(s) -def session_agent_list_result_to_dict(x: SessionAgentListResult) -> Any: - return to_class(SessionAgentListResult, x) +def fleet_start_result_to_dict(x: FleetStartResult) -> Any: + return to_class(FleetStartResult, x) +def fleet_start_request_from_dict(s: Any) -> FleetStartRequest: + return FleetStartRequest.from_dict(s) -def session_agent_get_current_result_from_dict(s: Any) -> SessionAgentGetCurrentResult: - return SessionAgentGetCurrentResult.from_dict(s) +def fleet_start_request_to_dict(x: FleetStartRequest) -> Any: + return to_class(FleetStartRequest, x) +def agent_list_from_dict(s: Any) -> AgentList: + return AgentList.from_dict(s) -def session_agent_get_current_result_to_dict(x: SessionAgentGetCurrentResult) -> Any: - return to_class(SessionAgentGetCurrentResult, x) +def agent_list_to_dict(x: AgentList) -> Any: + return to_class(AgentList, x) +def agent_current_from_dict(s: Any) -> AgentCurrent: + return AgentCurrent.from_dict(s) -def session_agent_select_result_from_dict(s: Any) -> SessionAgentSelectResult: - return SessionAgentSelectResult.from_dict(s) +def agent_current_to_dict(x: AgentCurrent) -> Any: + return to_class(AgentCurrent, x) +def agent_select_result_from_dict(s: Any) -> AgentSelectResult: + return AgentSelectResult.from_dict(s) -def session_agent_select_result_to_dict(x: SessionAgentSelectResult) -> Any: - return to_class(SessionAgentSelectResult, x) +def agent_select_result_to_dict(x: AgentSelectResult) -> Any: + return to_class(AgentSelectResult, x) +def agent_select_request_from_dict(s: Any) -> AgentSelectRequest: + return AgentSelectRequest.from_dict(s) -def session_agent_select_params_from_dict(s: Any) -> SessionAgentSelectParams: - return SessionAgentSelectParams.from_dict(s) +def agent_select_request_to_dict(x: AgentSelectRequest) -> Any: + return to_class(AgentSelectRequest, x) +def agent_deselect_from_dict(s: Any) -> AgentDeselect: + return AgentDeselect.from_dict(s) -def session_agent_select_params_to_dict(x: SessionAgentSelectParams) -> Any: - return to_class(SessionAgentSelectParams, x) +def agent_deselect_to_dict(x: AgentDeselect) -> Any: + return to_class(AgentDeselect, x) +def agent_reload_from_dict(s: Any) -> AgentReload: + return AgentReload.from_dict(s) -def session_agent_deselect_result_from_dict(s: Any) -> SessionAgentDeselectResult: - return SessionAgentDeselectResult.from_dict(s) +def agent_reload_to_dict(x: AgentReload) -> Any: + return to_class(AgentReload, x) +def skill_list_from_dict(s: Any) -> SkillList: + return SkillList.from_dict(s) -def session_agent_deselect_result_to_dict(x: SessionAgentDeselectResult) -> Any: - return to_class(SessionAgentDeselectResult, x) +def skill_list_to_dict(x: SkillList) -> Any: + return to_class(SkillList, x) +def skills_enable_result_from_dict(s: Any) -> SkillsEnableResult: + return SkillsEnableResult.from_dict(s) -def session_agent_reload_result_from_dict(s: Any) -> SessionAgentReloadResult: - return SessionAgentReloadResult.from_dict(s) +def skills_enable_result_to_dict(x: SkillsEnableResult) -> Any: + return to_class(SkillsEnableResult, x) +def skills_enable_request_from_dict(s: Any) -> SkillsEnableRequest: + return SkillsEnableRequest.from_dict(s) -def session_agent_reload_result_to_dict(x: SessionAgentReloadResult) -> Any: - return to_class(SessionAgentReloadResult, x) +def skills_enable_request_to_dict(x: SkillsEnableRequest) -> Any: + return to_class(SkillsEnableRequest, x) +def skills_disable_result_from_dict(s: Any) -> SkillsDisableResult: + return SkillsDisableResult.from_dict(s) -def session_skills_list_result_from_dict(s: Any) -> SessionSkillsListResult: - return SessionSkillsListResult.from_dict(s) +def skills_disable_result_to_dict(x: SkillsDisableResult) -> Any: + return to_class(SkillsDisableResult, x) +def skills_disable_request_from_dict(s: Any) -> SkillsDisableRequest: + return SkillsDisableRequest.from_dict(s) -def session_skills_list_result_to_dict(x: SessionSkillsListResult) -> Any: - return to_class(SessionSkillsListResult, x) +def skills_disable_request_to_dict(x: SkillsDisableRequest) -> Any: + return to_class(SkillsDisableRequest, x) +def skills_reload_from_dict(s: Any) -> SkillsReload: + return SkillsReload.from_dict(s) -def session_skills_enable_result_from_dict(s: Any) -> SessionSkillsEnableResult: - return SessionSkillsEnableResult.from_dict(s) +def skills_reload_to_dict(x: SkillsReload) -> Any: + return to_class(SkillsReload, x) +def mcp_list_from_dict(s: Any) -> MCPList: + return MCPList.from_dict(s) -def session_skills_enable_result_to_dict(x: SessionSkillsEnableResult) -> Any: - return to_class(SessionSkillsEnableResult, x) +def mcp_list_to_dict(x: MCPList) -> Any: + return to_class(MCPList, x) +def mcp_enable_result_from_dict(s: Any) -> MCPEnableResult: + return MCPEnableResult.from_dict(s) -def session_skills_enable_params_from_dict(s: Any) -> SessionSkillsEnableParams: - return SessionSkillsEnableParams.from_dict(s) +def mcp_enable_result_to_dict(x: MCPEnableResult) -> Any: + return to_class(MCPEnableResult, x) +def mcp_enable_request_from_dict(s: Any) -> MCPEnableRequest: + return MCPEnableRequest.from_dict(s) -def session_skills_enable_params_to_dict(x: SessionSkillsEnableParams) -> Any: - return to_class(SessionSkillsEnableParams, x) +def mcp_enable_request_to_dict(x: MCPEnableRequest) -> Any: + return to_class(MCPEnableRequest, x) +def mcp_disable_result_from_dict(s: Any) -> MCPDisableResult: + return MCPDisableResult.from_dict(s) -def session_skills_disable_result_from_dict(s: Any) -> SessionSkillsDisableResult: - return SessionSkillsDisableResult.from_dict(s) +def mcp_disable_result_to_dict(x: MCPDisableResult) -> Any: + return to_class(MCPDisableResult, x) +def mcp_disable_request_from_dict(s: Any) -> MCPDisableRequest: + return MCPDisableRequest.from_dict(s) -def session_skills_disable_result_to_dict(x: SessionSkillsDisableResult) -> Any: - return to_class(SessionSkillsDisableResult, x) +def mcp_disable_request_to_dict(x: MCPDisableRequest) -> Any: + return to_class(MCPDisableRequest, x) +def mcp_reload_from_dict(s: Any) -> MCPReload: + return MCPReload.from_dict(s) -def session_skills_disable_params_from_dict(s: Any) -> SessionSkillsDisableParams: - return SessionSkillsDisableParams.from_dict(s) +def mcp_reload_to_dict(x: MCPReload) -> Any: + return to_class(MCPReload, x) +def plugin_list_from_dict(s: Any) -> PluginList: + return PluginList.from_dict(s) -def session_skills_disable_params_to_dict(x: SessionSkillsDisableParams) -> Any: - return to_class(SessionSkillsDisableParams, x) +def plugin_list_to_dict(x: PluginList) -> Any: + return to_class(PluginList, x) +def extension_list_from_dict(s: Any) -> ExtensionList: + return ExtensionList.from_dict(s) -def session_skills_reload_result_from_dict(s: Any) -> SessionSkillsReloadResult: - return SessionSkillsReloadResult.from_dict(s) +def extension_list_to_dict(x: ExtensionList) -> Any: + return to_class(ExtensionList, x) +def extensions_enable_result_from_dict(s: Any) -> ExtensionsEnableResult: + return ExtensionsEnableResult.from_dict(s) -def session_skills_reload_result_to_dict(x: SessionSkillsReloadResult) -> Any: - return to_class(SessionSkillsReloadResult, x) +def extensions_enable_result_to_dict(x: ExtensionsEnableResult) -> Any: + return to_class(ExtensionsEnableResult, x) +def extensions_enable_request_from_dict(s: Any) -> ExtensionsEnableRequest: + return ExtensionsEnableRequest.from_dict(s) -def session_mcp_list_result_from_dict(s: Any) -> SessionMCPListResult: - return SessionMCPListResult.from_dict(s) +def extensions_enable_request_to_dict(x: ExtensionsEnableRequest) -> Any: + return to_class(ExtensionsEnableRequest, x) +def extensions_disable_result_from_dict(s: Any) -> ExtensionsDisableResult: + return ExtensionsDisableResult.from_dict(s) -def session_mcp_list_result_to_dict(x: SessionMCPListResult) -> Any: - return to_class(SessionMCPListResult, x) +def extensions_disable_result_to_dict(x: ExtensionsDisableResult) -> Any: + return to_class(ExtensionsDisableResult, x) +def extensions_disable_request_from_dict(s: Any) -> ExtensionsDisableRequest: + return ExtensionsDisableRequest.from_dict(s) -def session_mcp_enable_result_from_dict(s: Any) -> SessionMCPEnableResult: - return SessionMCPEnableResult.from_dict(s) +def extensions_disable_request_to_dict(x: ExtensionsDisableRequest) -> Any: + return to_class(ExtensionsDisableRequest, x) +def extensions_reload_from_dict(s: Any) -> ExtensionsReload: + return ExtensionsReload.from_dict(s) -def session_mcp_enable_result_to_dict(x: SessionMCPEnableResult) -> Any: - return to_class(SessionMCPEnableResult, x) +def extensions_reload_to_dict(x: ExtensionsReload) -> Any: + return to_class(ExtensionsReload, x) +def handle_tool_call_result_from_dict(s: Any) -> HandleToolCallResult: + return HandleToolCallResult.from_dict(s) -def session_mcp_enable_params_from_dict(s: Any) -> SessionMCPEnableParams: - return SessionMCPEnableParams.from_dict(s) +def handle_tool_call_result_to_dict(x: HandleToolCallResult) -> Any: + return to_class(HandleToolCallResult, x) +def tools_handle_pending_tool_call_request_from_dict(s: Any) -> ToolsHandlePendingToolCallRequest: + return ToolsHandlePendingToolCallRequest.from_dict(s) -def session_mcp_enable_params_to_dict(x: SessionMCPEnableParams) -> Any: - return to_class(SessionMCPEnableParams, x) +def tools_handle_pending_tool_call_request_to_dict(x: ToolsHandlePendingToolCallRequest) -> Any: + return to_class(ToolsHandlePendingToolCallRequest, x) +def commands_handle_pending_command_result_from_dict(s: Any) -> CommandsHandlePendingCommandResult: + return CommandsHandlePendingCommandResult.from_dict(s) -def session_mcp_disable_result_from_dict(s: Any) -> SessionMCPDisableResult: - return SessionMCPDisableResult.from_dict(s) +def commands_handle_pending_command_result_to_dict(x: CommandsHandlePendingCommandResult) -> Any: + return to_class(CommandsHandlePendingCommandResult, x) +def commands_handle_pending_command_request_from_dict(s: Any) -> CommandsHandlePendingCommandRequest: + return CommandsHandlePendingCommandRequest.from_dict(s) -def session_mcp_disable_result_to_dict(x: SessionMCPDisableResult) -> Any: - return to_class(SessionMCPDisableResult, x) +def commands_handle_pending_command_request_to_dict(x: CommandsHandlePendingCommandRequest) -> Any: + return to_class(CommandsHandlePendingCommandRequest, x) +def ui_elicitation_response_from_dict(s: Any) -> UIElicitationResponse: + return UIElicitationResponse.from_dict(s) -def session_mcp_disable_params_from_dict(s: Any) -> SessionMCPDisableParams: - return SessionMCPDisableParams.from_dict(s) +def ui_elicitation_response_to_dict(x: UIElicitationResponse) -> Any: + return to_class(UIElicitationResponse, x) +def ui_elicitation_request_from_dict(s: Any) -> UIElicitationRequest: + return UIElicitationRequest.from_dict(s) -def session_mcp_disable_params_to_dict(x: SessionMCPDisableParams) -> Any: - return to_class(SessionMCPDisableParams, x) +def ui_elicitation_request_to_dict(x: UIElicitationRequest) -> Any: + return to_class(UIElicitationRequest, x) +def ui_elicitation_result_from_dict(s: Any) -> UIElicitationResult: + return UIElicitationResult.from_dict(s) -def session_mcp_reload_result_from_dict(s: Any) -> SessionMCPReloadResult: - return SessionMCPReloadResult.from_dict(s) +def ui_elicitation_result_to_dict(x: UIElicitationResult) -> Any: + return to_class(UIElicitationResult, x) +def handle_pending_elicitation_request_from_dict(s: Any) -> HandlePendingElicitationRequest: + return HandlePendingElicitationRequest.from_dict(s) -def session_mcp_reload_result_to_dict(x: SessionMCPReloadResult) -> Any: - return to_class(SessionMCPReloadResult, x) +def handle_pending_elicitation_request_to_dict(x: HandlePendingElicitationRequest) -> Any: + return to_class(HandlePendingElicitationRequest, x) +def permission_request_result_from_dict(s: Any) -> PermissionRequestResult: + return PermissionRequestResult.from_dict(s) -def session_plugins_list_result_from_dict(s: Any) -> SessionPluginsListResult: - return SessionPluginsListResult.from_dict(s) +def permission_request_result_to_dict(x: PermissionRequestResult) -> Any: + return to_class(PermissionRequestResult, x) +def permission_decision_request_from_dict(s: Any) -> PermissionDecisionRequest: + return PermissionDecisionRequest.from_dict(s) -def session_plugins_list_result_to_dict(x: SessionPluginsListResult) -> Any: - return to_class(SessionPluginsListResult, x) +def permission_decision_request_to_dict(x: PermissionDecisionRequest) -> Any: + return to_class(PermissionDecisionRequest, x) +def log_result_from_dict(s: Any) -> LogResult: + return LogResult.from_dict(s) -def session_extensions_list_result_from_dict(s: Any) -> SessionExtensionsListResult: - return SessionExtensionsListResult.from_dict(s) +def log_result_to_dict(x: LogResult) -> Any: + return to_class(LogResult, x) +def log_request_from_dict(s: Any) -> LogRequest: + return LogRequest.from_dict(s) -def session_extensions_list_result_to_dict(x: SessionExtensionsListResult) -> Any: - return to_class(SessionExtensionsListResult, x) +def log_request_to_dict(x: LogRequest) -> Any: + return to_class(LogRequest, x) +def shell_exec_result_from_dict(s: Any) -> ShellExecResult: + return ShellExecResult.from_dict(s) -def session_extensions_enable_result_from_dict(s: Any) -> SessionExtensionsEnableResult: - return SessionExtensionsEnableResult.from_dict(s) +def shell_exec_result_to_dict(x: ShellExecResult) -> Any: + return to_class(ShellExecResult, x) +def shell_exec_request_from_dict(s: Any) -> ShellExecRequest: + return ShellExecRequest.from_dict(s) -def session_extensions_enable_result_to_dict(x: SessionExtensionsEnableResult) -> Any: - return to_class(SessionExtensionsEnableResult, x) +def shell_exec_request_to_dict(x: ShellExecRequest) -> Any: + return to_class(ShellExecRequest, x) +def shell_kill_result_from_dict(s: Any) -> ShellKillResult: + return ShellKillResult.from_dict(s) -def session_extensions_enable_params_from_dict(s: Any) -> SessionExtensionsEnableParams: - return SessionExtensionsEnableParams.from_dict(s) +def shell_kill_result_to_dict(x: ShellKillResult) -> Any: + return to_class(ShellKillResult, x) +def shell_kill_request_from_dict(s: Any) -> ShellKillRequest: + return ShellKillRequest.from_dict(s) -def session_extensions_enable_params_to_dict(x: SessionExtensionsEnableParams) -> Any: - return to_class(SessionExtensionsEnableParams, x) +def shell_kill_request_to_dict(x: ShellKillRequest) -> Any: + return to_class(ShellKillRequest, x) +def history_compact_from_dict(s: Any) -> HistoryCompact: + return HistoryCompact.from_dict(s) -def session_extensions_disable_result_from_dict(s: Any) -> SessionExtensionsDisableResult: - return SessionExtensionsDisableResult.from_dict(s) +def history_compact_to_dict(x: HistoryCompact) -> Any: + return to_class(HistoryCompact, x) +def history_truncate_result_from_dict(s: Any) -> HistoryTruncateResult: + return HistoryTruncateResult.from_dict(s) -def session_extensions_disable_result_to_dict(x: SessionExtensionsDisableResult) -> Any: - return to_class(SessionExtensionsDisableResult, x) +def history_truncate_result_to_dict(x: HistoryTruncateResult) -> Any: + return to_class(HistoryTruncateResult, x) +def history_truncate_request_from_dict(s: Any) -> HistoryTruncateRequest: + return HistoryTruncateRequest.from_dict(s) -def session_extensions_disable_params_from_dict(s: Any) -> SessionExtensionsDisableParams: - return SessionExtensionsDisableParams.from_dict(s) +def history_truncate_request_to_dict(x: HistoryTruncateRequest) -> Any: + return to_class(HistoryTruncateRequest, x) +def usage_metrics_from_dict(s: Any) -> UsageMetrics: + return UsageMetrics.from_dict(s) -def session_extensions_disable_params_to_dict(x: SessionExtensionsDisableParams) -> Any: - return to_class(SessionExtensionsDisableParams, x) - - -def session_extensions_reload_result_from_dict(s: Any) -> SessionExtensionsReloadResult: - return SessionExtensionsReloadResult.from_dict(s) - - -def session_extensions_reload_result_to_dict(x: SessionExtensionsReloadResult) -> Any: - return to_class(SessionExtensionsReloadResult, x) - - -def session_tools_handle_pending_tool_call_result_from_dict(s: Any) -> SessionToolsHandlePendingToolCallResult: - return SessionToolsHandlePendingToolCallResult.from_dict(s) - - -def session_tools_handle_pending_tool_call_result_to_dict(x: SessionToolsHandlePendingToolCallResult) -> Any: - return to_class(SessionToolsHandlePendingToolCallResult, x) - - -def session_tools_handle_pending_tool_call_params_from_dict(s: Any) -> SessionToolsHandlePendingToolCallParams: - return SessionToolsHandlePendingToolCallParams.from_dict(s) - - -def session_tools_handle_pending_tool_call_params_to_dict(x: SessionToolsHandlePendingToolCallParams) -> Any: - return to_class(SessionToolsHandlePendingToolCallParams, x) - - -def session_commands_handle_pending_command_result_from_dict(s: Any) -> SessionCommandsHandlePendingCommandResult: - return SessionCommandsHandlePendingCommandResult.from_dict(s) - - -def session_commands_handle_pending_command_result_to_dict(x: SessionCommandsHandlePendingCommandResult) -> Any: - return to_class(SessionCommandsHandlePendingCommandResult, x) - - -def session_commands_handle_pending_command_params_from_dict(s: Any) -> SessionCommandsHandlePendingCommandParams: - return SessionCommandsHandlePendingCommandParams.from_dict(s) - - -def session_commands_handle_pending_command_params_to_dict(x: SessionCommandsHandlePendingCommandParams) -> Any: - return to_class(SessionCommandsHandlePendingCommandParams, x) - - -def session_ui_elicitation_result_from_dict(s: Any) -> SessionUIElicitationResult: - return SessionUIElicitationResult.from_dict(s) - - -def session_ui_elicitation_result_to_dict(x: SessionUIElicitationResult) -> Any: - return to_class(SessionUIElicitationResult, x) - - -def session_ui_elicitation_params_from_dict(s: Any) -> SessionUIElicitationParams: - return SessionUIElicitationParams.from_dict(s) - - -def session_ui_elicitation_params_to_dict(x: SessionUIElicitationParams) -> Any: - return to_class(SessionUIElicitationParams, x) - - -def session_ui_handle_pending_elicitation_result_from_dict(s: Any) -> SessionUIHandlePendingElicitationResult: - return SessionUIHandlePendingElicitationResult.from_dict(s) - - -def session_ui_handle_pending_elicitation_result_to_dict(x: SessionUIHandlePendingElicitationResult) -> Any: - return to_class(SessionUIHandlePendingElicitationResult, x) - - -def session_ui_handle_pending_elicitation_params_from_dict(s: Any) -> SessionUIHandlePendingElicitationParams: - return SessionUIHandlePendingElicitationParams.from_dict(s) - - -def session_ui_handle_pending_elicitation_params_to_dict(x: SessionUIHandlePendingElicitationParams) -> Any: - return to_class(SessionUIHandlePendingElicitationParams, x) - - -def session_permissions_handle_pending_permission_request_result_from_dict(s: Any) -> SessionPermissionsHandlePendingPermissionRequestResult: - return SessionPermissionsHandlePendingPermissionRequestResult.from_dict(s) - - -def session_permissions_handle_pending_permission_request_result_to_dict(x: SessionPermissionsHandlePendingPermissionRequestResult) -> Any: - return to_class(SessionPermissionsHandlePendingPermissionRequestResult, x) - - -def session_permissions_handle_pending_permission_request_params_from_dict(s: Any) -> SessionPermissionsHandlePendingPermissionRequestParams: - return SessionPermissionsHandlePendingPermissionRequestParams.from_dict(s) - - -def session_permissions_handle_pending_permission_request_params_to_dict(x: SessionPermissionsHandlePendingPermissionRequestParams) -> Any: - return to_class(SessionPermissionsHandlePendingPermissionRequestParams, x) - - -def session_log_result_from_dict(s: Any) -> SessionLogResult: - return SessionLogResult.from_dict(s) - - -def session_log_result_to_dict(x: SessionLogResult) -> Any: - return to_class(SessionLogResult, x) - - -def session_log_params_from_dict(s: Any) -> SessionLogParams: - return SessionLogParams.from_dict(s) - - -def session_log_params_to_dict(x: SessionLogParams) -> Any: - return to_class(SessionLogParams, x) - - -def session_shell_exec_result_from_dict(s: Any) -> SessionShellExecResult: - return SessionShellExecResult.from_dict(s) - - -def session_shell_exec_result_to_dict(x: SessionShellExecResult) -> Any: - return to_class(SessionShellExecResult, x) - - -def session_shell_exec_params_from_dict(s: Any) -> SessionShellExecParams: - return SessionShellExecParams.from_dict(s) - - -def session_shell_exec_params_to_dict(x: SessionShellExecParams) -> Any: - return to_class(SessionShellExecParams, x) - - -def session_shell_kill_result_from_dict(s: Any) -> SessionShellKillResult: - return SessionShellKillResult.from_dict(s) - - -def session_shell_kill_result_to_dict(x: SessionShellKillResult) -> Any: - return to_class(SessionShellKillResult, x) - - -def session_shell_kill_params_from_dict(s: Any) -> SessionShellKillParams: - return SessionShellKillParams.from_dict(s) - - -def session_shell_kill_params_to_dict(x: SessionShellKillParams) -> Any: - return to_class(SessionShellKillParams, x) - - -def session_history_compact_result_from_dict(s: Any) -> SessionHistoryCompactResult: - return SessionHistoryCompactResult.from_dict(s) - - -def session_history_compact_result_to_dict(x: SessionHistoryCompactResult) -> Any: - return to_class(SessionHistoryCompactResult, x) - - -def session_history_truncate_result_from_dict(s: Any) -> SessionHistoryTruncateResult: - return SessionHistoryTruncateResult.from_dict(s) - - -def session_history_truncate_result_to_dict(x: SessionHistoryTruncateResult) -> Any: - return to_class(SessionHistoryTruncateResult, x) - - -def session_history_truncate_params_from_dict(s: Any) -> SessionHistoryTruncateParams: - return SessionHistoryTruncateParams.from_dict(s) - - -def session_history_truncate_params_to_dict(x: SessionHistoryTruncateParams) -> Any: - return to_class(SessionHistoryTruncateParams, x) - - -def session_usage_get_metrics_result_from_dict(s: Any) -> SessionUsageGetMetricsResult: - return SessionUsageGetMetricsResult.from_dict(s) - - -def session_usage_get_metrics_result_to_dict(x: SessionUsageGetMetricsResult) -> Any: - return to_class(SessionUsageGetMetricsResult, x) - +def usage_metrics_to_dict(x: UsageMetrics) -> Any: + return to_class(UsageMetrics, x) def session_fs_read_file_result_from_dict(s: Any) -> SessionFSReadFileResult: return SessionFSReadFileResult.from_dict(s) - def session_fs_read_file_result_to_dict(x: SessionFSReadFileResult) -> Any: return to_class(SessionFSReadFileResult, x) +def session_fs_read_file_request_from_dict(s: Any) -> SessionFSReadFileRequest: + return SessionFSReadFileRequest.from_dict(s) -def session_fs_read_file_params_from_dict(s: Any) -> SessionFSReadFileParams: - return SessionFSReadFileParams.from_dict(s) +def session_fs_read_file_request_to_dict(x: SessionFSReadFileRequest) -> Any: + return to_class(SessionFSReadFileRequest, x) +def session_fs_write_file_request_from_dict(s: Any) -> SessionFSWriteFileRequest: + return SessionFSWriteFileRequest.from_dict(s) -def session_fs_read_file_params_to_dict(x: SessionFSReadFileParams) -> Any: - return to_class(SessionFSReadFileParams, x) +def session_fs_write_file_request_to_dict(x: SessionFSWriteFileRequest) -> Any: + return to_class(SessionFSWriteFileRequest, x) +def session_fs_append_file_request_from_dict(s: Any) -> SessionFSAppendFileRequest: + return SessionFSAppendFileRequest.from_dict(s) -def session_fs_write_file_params_from_dict(s: Any) -> SessionFSWriteFileParams: - return SessionFSWriteFileParams.from_dict(s) - - -def session_fs_write_file_params_to_dict(x: SessionFSWriteFileParams) -> Any: - return to_class(SessionFSWriteFileParams, x) - - -def session_fs_append_file_params_from_dict(s: Any) -> SessionFSAppendFileParams: - return SessionFSAppendFileParams.from_dict(s) - - -def session_fs_append_file_params_to_dict(x: SessionFSAppendFileParams) -> Any: - return to_class(SessionFSAppendFileParams, x) - +def session_fs_append_file_request_to_dict(x: SessionFSAppendFileRequest) -> Any: + return to_class(SessionFSAppendFileRequest, x) def session_fs_exists_result_from_dict(s: Any) -> SessionFSExistsResult: return SessionFSExistsResult.from_dict(s) - def session_fs_exists_result_to_dict(x: SessionFSExistsResult) -> Any: return to_class(SessionFSExistsResult, x) +def session_fs_exists_request_from_dict(s: Any) -> SessionFSExistsRequest: + return SessionFSExistsRequest.from_dict(s) -def session_fs_exists_params_from_dict(s: Any) -> SessionFSExistsParams: - return SessionFSExistsParams.from_dict(s) - - -def session_fs_exists_params_to_dict(x: SessionFSExistsParams) -> Any: - return to_class(SessionFSExistsParams, x) - +def session_fs_exists_request_to_dict(x: SessionFSExistsRequest) -> Any: + return to_class(SessionFSExistsRequest, x) def session_fs_stat_result_from_dict(s: Any) -> SessionFSStatResult: return SessionFSStatResult.from_dict(s) - def session_fs_stat_result_to_dict(x: SessionFSStatResult) -> Any: return to_class(SessionFSStatResult, x) +def session_fs_stat_request_from_dict(s: Any) -> SessionFSStatRequest: + return SessionFSStatRequest.from_dict(s) -def session_fs_stat_params_from_dict(s: Any) -> SessionFSStatParams: - return SessionFSStatParams.from_dict(s) - - -def session_fs_stat_params_to_dict(x: SessionFSStatParams) -> Any: - return to_class(SessionFSStatParams, x) +def session_fs_stat_request_to_dict(x: SessionFSStatRequest) -> Any: + return to_class(SessionFSStatRequest, x) +def session_fs_mkdir_request_from_dict(s: Any) -> SessionFSMkdirRequest: + return SessionFSMkdirRequest.from_dict(s) -def session_fs_mkdir_params_from_dict(s: Any) -> SessionFSMkdirParams: - return SessionFSMkdirParams.from_dict(s) - - -def session_fs_mkdir_params_to_dict(x: SessionFSMkdirParams) -> Any: - return to_class(SessionFSMkdirParams, x) - +def session_fs_mkdir_request_to_dict(x: SessionFSMkdirRequest) -> Any: + return to_class(SessionFSMkdirRequest, x) def session_fs_readdir_result_from_dict(s: Any) -> SessionFSReaddirResult: return SessionFSReaddirResult.from_dict(s) - def session_fs_readdir_result_to_dict(x: SessionFSReaddirResult) -> Any: return to_class(SessionFSReaddirResult, x) +def session_fs_readdir_request_from_dict(s: Any) -> SessionFSReaddirRequest: + return SessionFSReaddirRequest.from_dict(s) -def session_fs_readdir_params_from_dict(s: Any) -> SessionFSReaddirParams: - return SessionFSReaddirParams.from_dict(s) - - -def session_fs_readdir_params_to_dict(x: SessionFSReaddirParams) -> Any: - return to_class(SessionFSReaddirParams, x) - +def session_fs_readdir_request_to_dict(x: SessionFSReaddirRequest) -> Any: + return to_class(SessionFSReaddirRequest, x) def session_fs_readdir_with_types_result_from_dict(s: Any) -> SessionFSReaddirWithTypesResult: return SessionFSReaddirWithTypesResult.from_dict(s) - def session_fs_readdir_with_types_result_to_dict(x: SessionFSReaddirWithTypesResult) -> Any: return to_class(SessionFSReaddirWithTypesResult, x) +def session_fs_readdir_with_types_request_from_dict(s: Any) -> SessionFSReaddirWithTypesRequest: + return SessionFSReaddirWithTypesRequest.from_dict(s) -def session_fs_readdir_with_types_params_from_dict(s: Any) -> SessionFSReaddirWithTypesParams: - return SessionFSReaddirWithTypesParams.from_dict(s) - - -def session_fs_readdir_with_types_params_to_dict(x: SessionFSReaddirWithTypesParams) -> Any: - return to_class(SessionFSReaddirWithTypesParams, x) - - -def session_fs_rm_params_from_dict(s: Any) -> SessionFSRmParams: - return SessionFSRmParams.from_dict(s) - - -def session_fs_rm_params_to_dict(x: SessionFSRmParams) -> Any: - return to_class(SessionFSRmParams, x) +def session_fs_readdir_with_types_request_to_dict(x: SessionFSReaddirWithTypesRequest) -> Any: + return to_class(SessionFSReaddirWithTypesRequest, x) +def session_fs_rm_request_from_dict(s: Any) -> SessionFSRmRequest: + return SessionFSRmRequest.from_dict(s) -def session_fs_rename_params_from_dict(s: Any) -> SessionFSRenameParams: - return SessionFSRenameParams.from_dict(s) +def session_fs_rm_request_to_dict(x: SessionFSRmRequest) -> Any: + return to_class(SessionFSRmRequest, x) +def session_fs_rename_request_from_dict(s: Any) -> SessionFSRenameRequest: + return SessionFSRenameRequest.from_dict(s) -def session_fs_rename_params_to_dict(x: SessionFSRenameParams) -> Any: - return to_class(SessionFSRenameParams, x) +def session_fs_rename_request_to_dict(x: SessionFSRenameRequest) -> Any: + return to_class(SessionFSRenameRequest, x) def _timeout_kwargs(timeout: float | None) -> dict: @@ -4207,32 +3773,32 @@ class ServerModelsApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def list(self, *, timeout: float | None = None) -> ModelsListResult: - return ModelsListResult.from_dict(await self._client.request("models.list", {}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> ModelList: + return ModelList.from_dict(await self._client.request("models.list", {}, **_timeout_kwargs(timeout))) class ServerToolsApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def list(self, params: ToolsListParams, *, timeout: float | None = None) -> ToolsListResult: + async def list(self, params: ToolsListRequest, *, timeout: float | None = None) -> ToolList: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} - return ToolsListResult.from_dict(await self._client.request("tools.list", params_dict, **_timeout_kwargs(timeout))) + return ToolList.from_dict(await self._client.request("tools.list", params_dict, **_timeout_kwargs(timeout))) class ServerAccountApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def get_quota(self, *, timeout: float | None = None) -> AccountGetQuotaResult: - return AccountGetQuotaResult.from_dict(await self._client.request("account.getQuota", {}, **_timeout_kwargs(timeout))) + async def get_quota(self, *, timeout: float | None = None) -> AccountQuota: + return AccountQuota.from_dict(await self._client.request("account.getQuota", {}, **_timeout_kwargs(timeout))) class ServerMcpApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def discover(self, params: MCPDiscoverParams, *, timeout: float | None = None) -> MCPDiscoverResult: + async def discover(self, params: MCPDiscoverRequest, *, timeout: float | None = None) -> MCPDiscoverResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} return MCPDiscoverResult.from_dict(await self._client.request("mcp.discover", params_dict, **_timeout_kwargs(timeout))) @@ -4241,7 +3807,7 @@ class ServerSessionFsApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def set_provider(self, params: SessionFSSetProviderParams, *, timeout: float | None = None) -> SessionFSSetProviderResult: + async def set_provider(self, params: SessionFSSetProviderRequest, *, timeout: float | None = None) -> SessionFSSetProviderResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} return SessionFSSetProviderResult.from_dict(await self._client.request("sessionFs.setProvider", params_dict, **_timeout_kwargs(timeout))) @@ -4251,7 +3817,7 @@ class ServerSessionsApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def fork(self, params: SessionsForkParams, *, timeout: float | None = None) -> SessionsForkResult: + async def fork(self, params: SessionsForkRequest, *, timeout: float | None = None) -> SessionsForkResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} return SessionsForkResult.from_dict(await self._client.request("sessions.fork", params_dict, **_timeout_kwargs(timeout))) @@ -4267,7 +3833,7 @@ def __init__(self, client: "JsonRpcClient"): self.session_fs = ServerSessionFsApi(client) self.sessions = ServerSessionsApi(client) - async def ping(self, params: PingParams, *, timeout: float | None = None) -> PingResult: + async def ping(self, params: PingRequest, *, timeout: float | None = None) -> PingResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} return PingResult.from_dict(await self._client.request("ping", params_dict, **_timeout_kwargs(timeout))) @@ -4277,13 +3843,13 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def get_current(self, *, timeout: float | None = None) -> SessionModelGetCurrentResult: - return SessionModelGetCurrentResult.from_dict(await self._client.request("session.model.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_current(self, *, timeout: float | None = None) -> ModelCurrent: + return ModelCurrent.from_dict(await self._client.request("session.model.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def switch_to(self, params: SessionModelSwitchToParams, *, timeout: float | None = None) -> SessionModelSwitchToResult: + async def switch_to(self, params: ModelSwitchToRequest, *, timeout: float | None = None) -> ModelSwitchToResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionModelSwitchToResult.from_dict(await self._client.request("session.model.switchTo", params_dict, **_timeout_kwargs(timeout))) + return ModelSwitchToResult.from_dict(await self._client.request("session.model.switchTo", params_dict, **_timeout_kwargs(timeout))) class ModeApi: @@ -4291,13 +3857,13 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def get(self, *, timeout: float | None = None) -> SessionModeGetResult: - return SessionModeGetResult.from_dict(await self._client.request("session.mode.get", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get(self, *, timeout: float | None = None) -> SessionMode: + return SessionMode(await self._client.request("session.mode.get", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def set(self, params: SessionModeSetParams, *, timeout: float | None = None) -> SessionModeSetResult: + async def set(self, params: ModeSetRequest, *, timeout: float | None = None) -> SessionMode: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionModeSetResult.from_dict(await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout))) + return SessionMode(await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout))) class PlanApi: @@ -4305,16 +3871,16 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def read(self, *, timeout: float | None = None) -> SessionPlanReadResult: - return SessionPlanReadResult.from_dict(await self._client.request("session.plan.read", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def read(self, *, timeout: float | None = None) -> Plan: + return Plan.from_dict(await self._client.request("session.plan.read", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def update(self, params: SessionPlanUpdateParams, *, timeout: float | None = None) -> SessionPlanUpdateResult: + async def update(self, params: PlanUpdateRequest, *, timeout: float | None = None) -> PlanUpdateResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionPlanUpdateResult.from_dict(await self._client.request("session.plan.update", params_dict, **_timeout_kwargs(timeout))) + return PlanUpdateResult.from_dict(await self._client.request("session.plan.update", params_dict, **_timeout_kwargs(timeout))) - async def delete(self, *, timeout: float | None = None) -> SessionPlanDeleteResult: - return SessionPlanDeleteResult.from_dict(await self._client.request("session.plan.delete", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def delete(self, *, timeout: float | None = None) -> PlanDelete: + return PlanDelete.from_dict(await self._client.request("session.plan.delete", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) class WorkspaceApi: @@ -4322,18 +3888,18 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list_files(self, *, timeout: float | None = None) -> SessionWorkspaceListFilesResult: - return SessionWorkspaceListFilesResult.from_dict(await self._client.request("session.workspace.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list_files(self, *, timeout: float | None = None) -> WorkspaceFiles: + return WorkspaceFiles.from_dict(await self._client.request("session.workspace.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def read_file(self, params: SessionWorkspaceReadFileParams, *, timeout: float | None = None) -> SessionWorkspaceReadFileResult: + async def read_file(self, params: WorkspaceReadFileRequest, *, timeout: float | None = None) -> WorkspaceReadFileResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionWorkspaceReadFileResult.from_dict(await self._client.request("session.workspace.readFile", params_dict, **_timeout_kwargs(timeout))) + return WorkspaceReadFileResult.from_dict(await self._client.request("session.workspace.readFile", params_dict, **_timeout_kwargs(timeout))) - async def create_file(self, params: SessionWorkspaceCreateFileParams, *, timeout: float | None = None) -> SessionWorkspaceCreateFileResult: + async def create_file(self, params: WorkspaceCreateFileRequest, *, timeout: float | None = None) -> WorkspaceCreateFileResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionWorkspaceCreateFileResult.from_dict(await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout))) + return WorkspaceCreateFileResult.from_dict(await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4342,10 +3908,10 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def start(self, params: SessionFleetStartParams, *, timeout: float | None = None) -> SessionFleetStartResult: + async def start(self, params: FleetStartRequest, *, timeout: float | None = None) -> FleetStartResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionFleetStartResult.from_dict(await self._client.request("session.fleet.start", params_dict, **_timeout_kwargs(timeout))) + return FleetStartResult.from_dict(await self._client.request("session.fleet.start", params_dict, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4354,22 +3920,22 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> SessionAgentListResult: - return SessionAgentListResult.from_dict(await self._client.request("session.agent.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> AgentList: + return AgentList.from_dict(await self._client.request("session.agent.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def get_current(self, *, timeout: float | None = None) -> SessionAgentGetCurrentResult: - return SessionAgentGetCurrentResult.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_current(self, *, timeout: float | None = None) -> AgentCurrent: + return AgentCurrent.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def select(self, params: SessionAgentSelectParams, *, timeout: float | None = None) -> SessionAgentSelectResult: + async def select(self, params: AgentSelectRequest, *, timeout: float | None = None) -> AgentSelectResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionAgentSelectResult.from_dict(await self._client.request("session.agent.select", params_dict, **_timeout_kwargs(timeout))) + return AgentSelectResult.from_dict(await self._client.request("session.agent.select", params_dict, **_timeout_kwargs(timeout))) - async def deselect(self, *, timeout: float | None = None) -> SessionAgentDeselectResult: - return SessionAgentDeselectResult.from_dict(await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def deselect(self, *, timeout: float | None = None) -> AgentDeselect: + return AgentDeselect.from_dict(await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def reload(self, *, timeout: float | None = None) -> SessionAgentReloadResult: - return SessionAgentReloadResult.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> AgentReload: + return AgentReload.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4378,21 +3944,21 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> SessionSkillsListResult: - return SessionSkillsListResult.from_dict(await self._client.request("session.skills.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> SkillList: + return SkillList.from_dict(await self._client.request("session.skills.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: SessionSkillsEnableParams, *, timeout: float | None = None) -> SessionSkillsEnableResult: + async def enable(self, params: SkillsEnableRequest, *, timeout: float | None = None) -> SkillsEnableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionSkillsEnableResult.from_dict(await self._client.request("session.skills.enable", params_dict, **_timeout_kwargs(timeout))) + return SkillsEnableResult.from_dict(await self._client.request("session.skills.enable", params_dict, **_timeout_kwargs(timeout))) - async def disable(self, params: SessionSkillsDisableParams, *, timeout: float | None = None) -> SessionSkillsDisableResult: + async def disable(self, params: SkillsDisableRequest, *, timeout: float | None = None) -> SkillsDisableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionSkillsDisableResult.from_dict(await self._client.request("session.skills.disable", params_dict, **_timeout_kwargs(timeout))) + return SkillsDisableResult.from_dict(await self._client.request("session.skills.disable", params_dict, **_timeout_kwargs(timeout))) - async def reload(self, *, timeout: float | None = None) -> SessionSkillsReloadResult: - return SessionSkillsReloadResult.from_dict(await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> SkillsReload: + return SkillsReload.from_dict(await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4401,21 +3967,21 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> SessionMCPListResult: - return SessionMCPListResult.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> MCPList: + return MCPList.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: SessionMCPEnableParams, *, timeout: float | None = None) -> SessionMCPEnableResult: + async def enable(self, params: MCPEnableRequest, *, timeout: float | None = None) -> MCPEnableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionMCPEnableResult.from_dict(await self._client.request("session.mcp.enable", params_dict, **_timeout_kwargs(timeout))) + return MCPEnableResult.from_dict(await self._client.request("session.mcp.enable", params_dict, **_timeout_kwargs(timeout))) - async def disable(self, params: SessionMCPDisableParams, *, timeout: float | None = None) -> SessionMCPDisableResult: + async def disable(self, params: MCPDisableRequest, *, timeout: float | None = None) -> MCPDisableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionMCPDisableResult.from_dict(await self._client.request("session.mcp.disable", params_dict, **_timeout_kwargs(timeout))) + return MCPDisableResult.from_dict(await self._client.request("session.mcp.disable", params_dict, **_timeout_kwargs(timeout))) - async def reload(self, *, timeout: float | None = None) -> SessionMCPReloadResult: - return SessionMCPReloadResult.from_dict(await self._client.request("session.mcp.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> MCPReload: + return MCPReload.from_dict(await self._client.request("session.mcp.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4424,8 +3990,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> SessionPluginsListResult: - return SessionPluginsListResult.from_dict(await self._client.request("session.plugins.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> PluginList: + return PluginList.from_dict(await self._client.request("session.plugins.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4434,21 +4000,21 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> SessionExtensionsListResult: - return SessionExtensionsListResult.from_dict(await self._client.request("session.extensions.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list(self, *, timeout: float | None = None) -> ExtensionList: + return ExtensionList.from_dict(await self._client.request("session.extensions.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: SessionExtensionsEnableParams, *, timeout: float | None = None) -> SessionExtensionsEnableResult: + async def enable(self, params: ExtensionsEnableRequest, *, timeout: float | None = None) -> ExtensionsEnableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionExtensionsEnableResult.from_dict(await self._client.request("session.extensions.enable", params_dict, **_timeout_kwargs(timeout))) + return ExtensionsEnableResult.from_dict(await self._client.request("session.extensions.enable", params_dict, **_timeout_kwargs(timeout))) - async def disable(self, params: SessionExtensionsDisableParams, *, timeout: float | None = None) -> SessionExtensionsDisableResult: + async def disable(self, params: ExtensionsDisableRequest, *, timeout: float | None = None) -> ExtensionsDisableResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionExtensionsDisableResult.from_dict(await self._client.request("session.extensions.disable", params_dict, **_timeout_kwargs(timeout))) + return ExtensionsDisableResult.from_dict(await self._client.request("session.extensions.disable", params_dict, **_timeout_kwargs(timeout))) - async def reload(self, *, timeout: float | None = None) -> SessionExtensionsReloadResult: - return SessionExtensionsReloadResult.from_dict(await self._client.request("session.extensions.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> ExtensionsReload: + return ExtensionsReload.from_dict(await self._client.request("session.extensions.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) class ToolsApi: @@ -4456,10 +4022,10 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def handle_pending_tool_call(self, params: SessionToolsHandlePendingToolCallParams, *, timeout: float | None = None) -> SessionToolsHandlePendingToolCallResult: + async def handle_pending_tool_call(self, params: ToolsHandlePendingToolCallRequest, *, timeout: float | None = None) -> HandleToolCallResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionToolsHandlePendingToolCallResult.from_dict(await self._client.request("session.tools.handlePendingToolCall", params_dict, **_timeout_kwargs(timeout))) + return HandleToolCallResult.from_dict(await self._client.request("session.tools.handlePendingToolCall", params_dict, **_timeout_kwargs(timeout))) class CommandsApi: @@ -4467,10 +4033,10 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def handle_pending_command(self, params: SessionCommandsHandlePendingCommandParams, *, timeout: float | None = None) -> SessionCommandsHandlePendingCommandResult: + async def handle_pending_command(self, params: CommandsHandlePendingCommandRequest, *, timeout: float | None = None) -> CommandsHandlePendingCommandResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionCommandsHandlePendingCommandResult.from_dict(await self._client.request("session.commands.handlePendingCommand", params_dict, **_timeout_kwargs(timeout))) + return CommandsHandlePendingCommandResult.from_dict(await self._client.request("session.commands.handlePendingCommand", params_dict, **_timeout_kwargs(timeout))) class UiApi: @@ -4478,15 +4044,15 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def elicitation(self, params: SessionUIElicitationParams, *, timeout: float | None = None) -> SessionUIElicitationResult: + async def elicitation(self, params: UIElicitationRequest, *, timeout: float | None = None) -> UIElicitationResponse: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionUIElicitationResult.from_dict(await self._client.request("session.ui.elicitation", params_dict, **_timeout_kwargs(timeout))) + return UIElicitationResponse.from_dict(await self._client.request("session.ui.elicitation", params_dict, **_timeout_kwargs(timeout))) - async def handle_pending_elicitation(self, params: SessionUIHandlePendingElicitationParams, *, timeout: float | None = None) -> SessionUIHandlePendingElicitationResult: + async def handle_pending_elicitation(self, params: HandlePendingElicitationRequest, *, timeout: float | None = None) -> UIElicitationResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionUIHandlePendingElicitationResult.from_dict(await self._client.request("session.ui.handlePendingElicitation", params_dict, **_timeout_kwargs(timeout))) + return UIElicitationResult.from_dict(await self._client.request("session.ui.handlePendingElicitation", params_dict, **_timeout_kwargs(timeout))) class PermissionsApi: @@ -4494,10 +4060,10 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def handle_pending_permission_request(self, params: SessionPermissionsHandlePendingPermissionRequestParams, *, timeout: float | None = None) -> SessionPermissionsHandlePendingPermissionRequestResult: + async def handle_pending_permission_request(self, params: PermissionDecisionRequest, *, timeout: float | None = None) -> PermissionRequestResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionPermissionsHandlePendingPermissionRequestResult.from_dict(await self._client.request("session.permissions.handlePendingPermissionRequest", params_dict, **_timeout_kwargs(timeout))) + return PermissionRequestResult.from_dict(await self._client.request("session.permissions.handlePendingPermissionRequest", params_dict, **_timeout_kwargs(timeout))) class ShellApi: @@ -4505,15 +4071,15 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def exec(self, params: SessionShellExecParams, *, timeout: float | None = None) -> SessionShellExecResult: + async def exec(self, params: ShellExecRequest, *, timeout: float | None = None) -> ShellExecResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionShellExecResult.from_dict(await self._client.request("session.shell.exec", params_dict, **_timeout_kwargs(timeout))) + return ShellExecResult.from_dict(await self._client.request("session.shell.exec", params_dict, **_timeout_kwargs(timeout))) - async def kill(self, params: SessionShellKillParams, *, timeout: float | None = None) -> SessionShellKillResult: + async def kill(self, params: ShellKillRequest, *, timeout: float | None = None) -> ShellKillResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionShellKillResult.from_dict(await self._client.request("session.shell.kill", params_dict, **_timeout_kwargs(timeout))) + return ShellKillResult.from_dict(await self._client.request("session.shell.kill", params_dict, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4522,13 +4088,13 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def compact(self, *, timeout: float | None = None) -> SessionHistoryCompactResult: - return SessionHistoryCompactResult.from_dict(await self._client.request("session.history.compact", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def compact(self, *, timeout: float | None = None) -> HistoryCompact: + return HistoryCompact.from_dict(await self._client.request("session.history.compact", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def truncate(self, params: SessionHistoryTruncateParams, *, timeout: float | None = None) -> SessionHistoryTruncateResult: + async def truncate(self, params: HistoryTruncateRequest, *, timeout: float | None = None) -> HistoryTruncateResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionHistoryTruncateResult.from_dict(await self._client.request("session.history.truncate", params_dict, **_timeout_kwargs(timeout))) + return HistoryTruncateResult.from_dict(await self._client.request("session.history.truncate", params_dict, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -4537,8 +4103,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def get_metrics(self, *, timeout: float | None = None) -> SessionUsageGetMetricsResult: - return SessionUsageGetMetricsResult.from_dict(await self._client.request("session.usage.getMetrics", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_metrics(self, *, timeout: float | None = None) -> UsageMetrics: + return UsageMetrics.from_dict(await self._client.request("session.usage.getMetrics", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) class SessionRpc: @@ -4564,32 +4130,32 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self.history = HistoryApi(client, session_id) self.usage = UsageApi(client, session_id) - async def log(self, params: SessionLogParams, *, timeout: float | None = None) -> SessionLogResult: + async def log(self, params: LogRequest, *, timeout: float | None = None) -> LogResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionLogResult.from_dict(await self._client.request("session.log", params_dict, **_timeout_kwargs(timeout))) + return LogResult.from_dict(await self._client.request("session.log", params_dict, **_timeout_kwargs(timeout))) class SessionFsHandler(Protocol): - async def read_file(self, params: SessionFSReadFileParams) -> SessionFSReadFileResult: + async def read_file(self, params: SessionFSReadFileRequest) -> SessionFSReadFileResult: pass - async def write_file(self, params: SessionFSWriteFileParams) -> None: + async def write_file(self, params: SessionFSWriteFileRequest) -> None: pass - async def append_file(self, params: SessionFSAppendFileParams) -> None: + async def append_file(self, params: SessionFSAppendFileRequest) -> None: pass - async def exists(self, params: SessionFSExistsParams) -> SessionFSExistsResult: + async def exists(self, params: SessionFSExistsRequest) -> SessionFSExistsResult: pass - async def stat(self, params: SessionFSStatParams) -> SessionFSStatResult: + async def stat(self, params: SessionFSStatRequest) -> SessionFSStatResult: pass - async def mkdir(self, params: SessionFSMkdirParams) -> None: + async def mkdir(self, params: SessionFSMkdirRequest) -> None: pass - async def readdir(self, params: SessionFSReaddirParams) -> SessionFSReaddirResult: + async def readdir(self, params: SessionFSReaddirRequest) -> SessionFSReaddirResult: pass - async def readdir_with_types(self, params: SessionFSReaddirWithTypesParams) -> SessionFSReaddirWithTypesResult: + async def readdir_with_types(self, params: SessionFSReaddirWithTypesRequest) -> SessionFSReaddirWithTypesResult: pass - async def rm(self, params: SessionFSRmParams) -> None: + async def rm(self, params: SessionFSRmRequest) -> None: pass - async def rename(self, params: SessionFSRenameParams) -> None: + async def rename(self, params: SessionFSRenameRequest) -> None: pass @dataclass @@ -4602,70 +4168,70 @@ def register_client_session_api_handlers( ) -> None: """Register client-session request handlers on a JSON-RPC connection.""" async def handle_session_fs_read_file(params: dict) -> dict | None: - request = SessionFSReadFileParams.from_dict(params) + request = SessionFSReadFileRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") result = await handler.read_file(request) return result.to_dict() client.set_request_handler("sessionFs.readFile", handle_session_fs_read_file) async def handle_session_fs_write_file(params: dict) -> dict | None: - request = SessionFSWriteFileParams.from_dict(params) + request = SessionFSWriteFileRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") await handler.write_file(request) return None client.set_request_handler("sessionFs.writeFile", handle_session_fs_write_file) async def handle_session_fs_append_file(params: dict) -> dict | None: - request = SessionFSAppendFileParams.from_dict(params) + request = SessionFSAppendFileRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") await handler.append_file(request) return None client.set_request_handler("sessionFs.appendFile", handle_session_fs_append_file) async def handle_session_fs_exists(params: dict) -> dict | None: - request = SessionFSExistsParams.from_dict(params) + request = SessionFSExistsRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") result = await handler.exists(request) return result.to_dict() client.set_request_handler("sessionFs.exists", handle_session_fs_exists) async def handle_session_fs_stat(params: dict) -> dict | None: - request = SessionFSStatParams.from_dict(params) + request = SessionFSStatRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") result = await handler.stat(request) return result.to_dict() client.set_request_handler("sessionFs.stat", handle_session_fs_stat) async def handle_session_fs_mkdir(params: dict) -> dict | None: - request = SessionFSMkdirParams.from_dict(params) + request = SessionFSMkdirRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") await handler.mkdir(request) return None client.set_request_handler("sessionFs.mkdir", handle_session_fs_mkdir) async def handle_session_fs_readdir(params: dict) -> dict | None: - request = SessionFSReaddirParams.from_dict(params) + request = SessionFSReaddirRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") result = await handler.readdir(request) return result.to_dict() client.set_request_handler("sessionFs.readdir", handle_session_fs_readdir) async def handle_session_fs_readdir_with_types(params: dict) -> dict | None: - request = SessionFSReaddirWithTypesParams.from_dict(params) + request = SessionFSReaddirWithTypesRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") result = await handler.readdir_with_types(request) return result.to_dict() client.set_request_handler("sessionFs.readdirWithTypes", handle_session_fs_readdir_with_types) async def handle_session_fs_rm(params: dict) -> dict | None: - request = SessionFSRmParams.from_dict(params) + request = SessionFSRmRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") await handler.rm(request) return None client.set_request_handler("sessionFs.rm", handle_session_fs_rm) async def handle_session_fs_rename(params: dict) -> dict | None: - request = SessionFSRenameParams.from_dict(params) + request = SessionFSRenameRequest.from_dict(params) handler = get_handlers(request.session_id).session_fs if handler is None: raise RuntimeError(f"No session_fs handler registered for session: {request.session_id}") await handler.rename(request) diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index 2c29c791a..2c1dbffb6 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -78,7 +78,7 @@ def from_int(x: Any) -> int: return x -class DataAction(Enum): +class ElicitationCompletedAction(Enum): """The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) """ @@ -87,7 +87,7 @@ class DataAction(Enum): DECLINE = "decline" -class AgentMode(Enum): +class UserMessageAgentMode(Enum): """The agent mode that was active when this message was sent""" AUTOPILOT = "autopilot" @@ -97,7 +97,7 @@ class AgentMode(Enum): @dataclass -class Agent: +class CustomAgentsUpdatedAgent: description: str """Description of what the agent does""" @@ -123,7 +123,7 @@ class Agent: """Model override for this agent, if set""" @staticmethod - def from_dict(obj: Any) -> 'Agent': + def from_dict(obj: Any) -> 'CustomAgentsUpdatedAgent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) @@ -133,7 +133,7 @@ def from_dict(obj: Any) -> 'Agent': 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 Agent(description, display_name, id, name, source, tools, user_invocable, model) + return CustomAgentsUpdatedAgent(description, display_name, id, name, source, tools, user_invocable, model) def to_dict(self) -> dict: result: dict = {} @@ -150,7 +150,7 @@ def to_dict(self) -> dict: @dataclass -class LineRange: +class UserMessageAttachmentFileLineRange: """Optional line range to scope the attachment to a specific section of the file""" end: float @@ -160,11 +160,11 @@ class LineRange: """Start line number (1-based)""" @staticmethod - def from_dict(obj: Any) -> 'LineRange': + def from_dict(obj: Any) -> 'UserMessageAttachmentFileLineRange': assert isinstance(obj, dict) end = from_float(obj.get("end")) start = from_float(obj.get("start")) - return LineRange(end, start) + return UserMessageAttachmentFileLineRange(end, start) def to_dict(self) -> dict: result: dict = {} @@ -173,7 +173,7 @@ def to_dict(self) -> dict: return result -class ReferenceType(Enum): +class UserMessageAttachmentGithubReferenceType(Enum): """Type of GitHub reference""" DISCUSSION = "discussion" @@ -182,7 +182,7 @@ class ReferenceType(Enum): @dataclass -class End: +class UserMessageAttachmentSelectionDetailsEnd: """End position of the selection""" character: float @@ -192,11 +192,11 @@ class End: """End line number (0-based)""" @staticmethod - def from_dict(obj: Any) -> 'End': + def from_dict(obj: Any) -> 'UserMessageAttachmentSelectionDetailsEnd': assert isinstance(obj, dict) character = from_float(obj.get("character")) line = from_float(obj.get("line")) - return End(character, line) + return UserMessageAttachmentSelectionDetailsEnd(character, line) def to_dict(self) -> dict: result: dict = {} @@ -206,7 +206,7 @@ def to_dict(self) -> dict: @dataclass -class Start: +class UserMessageAttachmentSelectionDetailsStart: """Start position of the selection""" character: float @@ -216,11 +216,11 @@ class Start: """Start line number (0-based)""" @staticmethod - def from_dict(obj: Any) -> 'Start': + def from_dict(obj: Any) -> 'UserMessageAttachmentSelectionDetailsStart': assert isinstance(obj, dict) character = from_float(obj.get("character")) line = from_float(obj.get("line")) - return Start(character, line) + return UserMessageAttachmentSelectionDetailsStart(character, line) def to_dict(self) -> dict: result: dict = {} @@ -230,30 +230,30 @@ def to_dict(self) -> dict: @dataclass -class Selection: +class UserMessageAttachmentSelectionDetails: """Position range of the selection within the file""" - end: End + end: UserMessageAttachmentSelectionDetailsEnd """End position of the selection""" - start: Start + start: UserMessageAttachmentSelectionDetailsStart """Start position of the selection""" @staticmethod - def from_dict(obj: Any) -> 'Selection': + def from_dict(obj: Any) -> 'UserMessageAttachmentSelectionDetails': assert isinstance(obj, dict) - end = End.from_dict(obj.get("end")) - start = Start.from_dict(obj.get("start")) - return Selection(end, start) + end = UserMessageAttachmentSelectionDetailsEnd.from_dict(obj.get("end")) + start = UserMessageAttachmentSelectionDetailsStart.from_dict(obj.get("start")) + return UserMessageAttachmentSelectionDetails(end, start) def to_dict(self) -> dict: result: dict = {} - result["end"] = to_class(End, self.end) - result["start"] = to_class(Start, self.start) + result["end"] = to_class(UserMessageAttachmentSelectionDetailsEnd, self.end) + result["start"] = to_class(UserMessageAttachmentSelectionDetailsStart, self.start) return result -class AttachmentType(Enum): +class UserMessageAttachmentType(Enum): BLOB = "blob" DIRECTORY = "directory" FILE = "file" @@ -262,7 +262,7 @@ class AttachmentType(Enum): @dataclass -class Attachment: +class UserMessageAttachment: """A user message attachment — a file, directory, code selection, blob, or GitHub reference File attachment @@ -275,7 +275,7 @@ class Attachment: Blob attachment with inline base64-encoded data """ - type: AttachmentType + type: UserMessageAttachmentType """Attachment type discriminator""" display_name: str | None = None @@ -283,7 +283,7 @@ class Attachment: User-facing display name for the selection """ - line_range: LineRange | None = None + line_range: UserMessageAttachmentFileLineRange | None = None """Optional line range to scope the attachment to a specific section of the file""" path: str | None = None @@ -294,7 +294,7 @@ class Attachment: file_path: str | None = None """Absolute path to the file containing the selection""" - selection: Selection | None = None + selection: UserMessageAttachmentSelectionDetails | None = None """Position range of the selection within the file""" text: str | None = None @@ -303,7 +303,7 @@ class Attachment: number: float | None = None """Issue, pull request, or discussion number""" - reference_type: ReferenceType | None = None + reference_type: UserMessageAttachmentGithubReferenceType | None = None """Type of GitHub reference""" state: str | None = None @@ -322,43 +322,43 @@ class Attachment: """MIME type of the inline data""" @staticmethod - def from_dict(obj: Any) -> 'Attachment': + def from_dict(obj: Any) -> 'UserMessageAttachment': assert isinstance(obj, dict) - type = AttachmentType(obj.get("type")) + type = UserMessageAttachmentType(obj.get("type")) display_name = from_union([from_str, from_none], obj.get("displayName")) - line_range = from_union([LineRange.from_dict, from_none], obj.get("lineRange")) + line_range = from_union([UserMessageAttachmentFileLineRange.from_dict, from_none], obj.get("lineRange")) path = from_union([from_str, from_none], obj.get("path")) file_path = from_union([from_str, from_none], obj.get("filePath")) - selection = from_union([Selection.from_dict, from_none], obj.get("selection")) + selection = from_union([UserMessageAttachmentSelectionDetails.from_dict, from_none], obj.get("selection")) text = from_union([from_str, from_none], obj.get("text")) number = from_union([from_float, from_none], obj.get("number")) - reference_type = from_union([ReferenceType, from_none], obj.get("referenceType")) + reference_type = from_union([UserMessageAttachmentGithubReferenceType, from_none], obj.get("referenceType")) state = from_union([from_str, from_none], obj.get("state")) title = from_union([from_str, from_none], obj.get("title")) url = from_union([from_str, from_none], obj.get("url")) data = from_union([from_str, from_none], obj.get("data")) mime_type = from_union([from_str, from_none], obj.get("mimeType")) - return Attachment(type, display_name, line_range, path, file_path, selection, text, number, reference_type, state, title, url, data, mime_type) + return UserMessageAttachment(type, display_name, line_range, path, file_path, selection, text, number, reference_type, state, title, url, data, mime_type) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(AttachmentType, self.type) + result["type"] = to_enum(UserMessageAttachmentType, self.type) if self.display_name is not None: result["displayName"] = from_union([from_str, from_none], self.display_name) if self.line_range is not None: - result["lineRange"] = from_union([lambda x: to_class(LineRange, x), from_none], self.line_range) + result["lineRange"] = from_union([lambda x: to_class(UserMessageAttachmentFileLineRange, x), from_none], self.line_range) if self.path is not None: result["path"] = from_union([from_str, from_none], self.path) if self.file_path is not None: result["filePath"] = from_union([from_str, from_none], self.file_path) if self.selection is not None: - result["selection"] = from_union([lambda x: to_class(Selection, x), from_none], self.selection) + result["selection"] = from_union([lambda x: to_class(UserMessageAttachmentSelectionDetails, x), from_none], self.selection) if self.text is not None: result["text"] = from_union([from_str, from_none], self.text) if self.number is not None: result["number"] = from_union([to_float, from_none], self.number) if self.reference_type is not None: - result["referenceType"] = from_union([lambda x: to_enum(ReferenceType, x), from_none], self.reference_type) + result["referenceType"] = from_union([lambda x: to_enum(UserMessageAttachmentGithubReferenceType, x), from_none], self.reference_type) if self.state is not None: result["state"] = from_union([from_str, from_none], self.state) if self.title is not None: @@ -373,7 +373,7 @@ def to_dict(self) -> dict: @dataclass -class CodeChanges: +class ShutdownCodeChanges: """Aggregate code change metrics for the session""" files_modified: list[str] @@ -386,12 +386,12 @@ class CodeChanges: """Total number of lines removed during the session""" @staticmethod - def from_dict(obj: Any) -> 'CodeChanges': + def from_dict(obj: Any) -> 'ShutdownCodeChanges': assert isinstance(obj, dict) files_modified = from_list(from_str, obj.get("filesModified")) lines_added = from_float(obj.get("linesAdded")) lines_removed = from_float(obj.get("linesRemoved")) - return CodeChanges(files_modified, lines_added, lines_removed) + return ShutdownCodeChanges(files_modified, lines_added, lines_removed) def to_dict(self) -> dict: result: dict = {} @@ -402,16 +402,16 @@ def to_dict(self) -> dict: @dataclass -class DataCommand: +class CommandsChangedCommand: name: str description: str | None = None @staticmethod - def from_dict(obj: Any) -> 'DataCommand': + def from_dict(obj: Any) -> 'CommandsChangedCommand': assert isinstance(obj, dict) name = from_str(obj.get("name")) description = from_union([from_str, from_none], obj.get("description")) - return DataCommand(name, description) + return CommandsChangedCommand(name, description) def to_dict(self) -> dict: result: dict = {} @@ -422,7 +422,7 @@ def to_dict(self) -> dict: @dataclass -class CompactionTokensUsed: +class CompactionCompleteCompactionTokensUsed: """Token usage breakdown for the compaction LLM call""" cached_input: float @@ -435,12 +435,12 @@ class CompactionTokensUsed: """Output tokens produced by the compaction LLM call""" @staticmethod - def from_dict(obj: Any) -> 'CompactionTokensUsed': + def from_dict(obj: Any) -> 'CompactionCompleteCompactionTokensUsed': assert isinstance(obj, dict) cached_input = from_float(obj.get("cachedInput")) input = from_float(obj.get("input")) output = from_float(obj.get("output")) - return CompactionTokensUsed(cached_input, input, output) + return CompactionCompleteCompactionTokensUsed(cached_input, input, output) def to_dict(self) -> dict: result: dict = {} @@ -450,7 +450,7 @@ def to_dict(self) -> dict: return result -class HostType(Enum): +class ContextChangedHostType(Enum): """Hosting platform type of the repository (github or ado)""" ADO = "ado" @@ -458,7 +458,7 @@ class HostType(Enum): @dataclass -class ContextClass: +class Context: """Working directory and git context at session start Updated working directory and git context at resume time @@ -478,7 +478,7 @@ class ContextClass: head_commit: str | None = None """Head commit of current git branch at session start time""" - host_type: HostType | None = None + host_type: ContextChangedHostType | None = None """Hosting platform type of the repository (github or ado)""" repository: str | None = None @@ -487,16 +487,16 @@ class ContextClass: """ @staticmethod - def from_dict(obj: Any) -> 'ContextClass': + def from_dict(obj: Any) -> 'Context': assert isinstance(obj, dict) cwd = from_str(obj.get("cwd")) base_commit = from_union([from_str, from_none], obj.get("baseCommit")) branch = from_union([from_str, from_none], obj.get("branch")) git_root = from_union([from_str, from_none], obj.get("gitRoot")) head_commit = from_union([from_str, from_none], obj.get("headCommit")) - host_type = from_union([HostType, from_none], obj.get("hostType")) + host_type = from_union([ContextChangedHostType, from_none], obj.get("hostType")) repository = from_union([from_str, from_none], obj.get("repository")) - return ContextClass(cwd, base_commit, branch, git_root, head_commit, host_type, repository) + return Context(cwd, base_commit, branch, git_root, head_commit, host_type, repository) def to_dict(self) -> dict: result: dict = {} @@ -510,14 +510,14 @@ def to_dict(self) -> dict: if self.head_commit is not None: result["headCommit"] = from_union([from_str, from_none], self.head_commit) if self.host_type is not None: - result["hostType"] = from_union([lambda x: to_enum(HostType, x), from_none], self.host_type) + result["hostType"] = from_union([lambda x: to_enum(ContextChangedHostType, x), from_none], self.host_type) if self.repository is not None: result["repository"] = from_union([from_str, from_none], self.repository) return result @dataclass -class TokenDetail: +class AssistantUsageCopilotUsageTokenDetail: """Token usage detail for a single billing category""" batch_size: float @@ -533,13 +533,13 @@ class TokenDetail: """Token category (e.g., "input", "output")""" @staticmethod - def from_dict(obj: Any) -> 'TokenDetail': + def from_dict(obj: Any) -> 'AssistantUsageCopilotUsageTokenDetail': assert isinstance(obj, dict) batch_size = from_float(obj.get("batchSize")) cost_per_batch = from_float(obj.get("costPerBatch")) token_count = from_float(obj.get("tokenCount")) token_type = from_str(obj.get("tokenType")) - return TokenDetail(batch_size, cost_per_batch, token_count, token_type) + return AssistantUsageCopilotUsageTokenDetail(batch_size, cost_per_batch, token_count, token_type) def to_dict(self) -> dict: result: dict = {} @@ -551,31 +551,31 @@ def to_dict(self) -> dict: @dataclass -class CopilotUsage: +class AssistantUsageCopilotUsage: """Per-request cost and usage data from the CAPI copilot_usage response field""" - token_details: list[TokenDetail] + token_details: list[AssistantUsageCopilotUsageTokenDetail] """Itemized token usage breakdown""" total_nano_aiu: float """Total cost in nano-AIU (AI Units) for this request""" @staticmethod - def from_dict(obj: Any) -> 'CopilotUsage': + def from_dict(obj: Any) -> 'AssistantUsageCopilotUsage': assert isinstance(obj, dict) - token_details = from_list(TokenDetail.from_dict, obj.get("tokenDetails")) + token_details = from_list(AssistantUsageCopilotUsageTokenDetail.from_dict, obj.get("tokenDetails")) total_nano_aiu = from_float(obj.get("totalNanoAiu")) - return CopilotUsage(token_details, total_nano_aiu) + return AssistantUsageCopilotUsage(token_details, total_nano_aiu) def to_dict(self) -> dict: result: dict = {} - result["tokenDetails"] = from_list(lambda x: to_class(TokenDetail, x), self.token_details) + result["tokenDetails"] = from_list(lambda x: to_class(AssistantUsageCopilotUsageTokenDetail, x), self.token_details) result["totalNanoAiu"] = to_float(self.total_nano_aiu) return result @dataclass -class ErrorClass: +class Error: """Error details when the tool execution failed Error details when the hook failed @@ -590,12 +590,12 @@ class ErrorClass: """Error stack trace, when available""" @staticmethod - def from_dict(obj: Any) -> 'ErrorClass': + def from_dict(obj: Any) -> 'Error': assert isinstance(obj, dict) message = from_str(obj.get("message")) code = from_union([from_str, from_none], obj.get("code")) stack = from_union([from_str, from_none], obj.get("stack")) - return ErrorClass(message, code, stack) + return Error(message, code, stack) def to_dict(self) -> dict: result: dict = {} @@ -607,14 +607,14 @@ def to_dict(self) -> dict: return result -class Source(Enum): +class ExtensionsLoadedExtensionSource(Enum): """Discovery source""" PROJECT = "project" USER = "user" -class ExtensionStatus(Enum): +class ExtensionsLoadedExtensionStatus(Enum): """Current status: running, disabled, failed, or starting""" DISABLED = "disabled" @@ -624,45 +624,45 @@ class ExtensionStatus(Enum): @dataclass -class Extension: +class ExtensionsLoadedExtension: id: str """Source-qualified extension ID (e.g., 'project:my-ext', 'user:auth-helper')""" name: str """Extension name (directory name)""" - source: Source + source: ExtensionsLoadedExtensionSource """Discovery source""" - status: ExtensionStatus + status: ExtensionsLoadedExtensionStatus """Current status: running, disabled, failed, or starting""" @staticmethod - def from_dict(obj: Any) -> 'Extension': + def from_dict(obj: Any) -> 'ExtensionsLoadedExtension': assert isinstance(obj, dict) id = from_str(obj.get("id")) name = from_str(obj.get("name")) - source = Source(obj.get("source")) - status = ExtensionStatus(obj.get("status")) - return Extension(id, name, source, status) + source = ExtensionsLoadedExtensionSource(obj.get("source")) + status = ExtensionsLoadedExtensionStatus(obj.get("status")) + return ExtensionsLoadedExtension(id, name, source, status) def to_dict(self) -> dict: result: dict = {} result["id"] = from_str(self.id) result["name"] = from_str(self.name) - result["source"] = to_enum(Source, self.source) - result["status"] = to_enum(ExtensionStatus, self.status) + result["source"] = to_enum(ExtensionsLoadedExtensionSource, self.source) + result["status"] = to_enum(ExtensionsLoadedExtensionStatus, self.status) return result -class KindStatus(Enum): +class SystemNotificationAgentCompletedStatus(Enum): """Whether the agent completed successfully or failed""" COMPLETED = "completed" FAILED = "failed" -class KindType(Enum): +class SystemNotificationType(Enum): AGENT_COMPLETED = "agent_completed" AGENT_IDLE = "agent_idle" SHELL_COMPLETED = "shell_completed" @@ -670,10 +670,10 @@ class KindType(Enum): @dataclass -class KindClass: +class SystemNotification: """Structured metadata identifying what triggered this notification""" - type: KindType + type: SystemNotificationType agent_id: str | None = None """Unique identifier of the background agent""" @@ -688,7 +688,7 @@ class KindClass: prompt: str | None = None """The full prompt given to the background agent""" - status: KindStatus | None = None + status: SystemNotificationAgentCompletedStatus | None = None """Whether the agent completed successfully or failed""" exit_code: float | None = None @@ -701,21 +701,21 @@ class KindClass: """ @staticmethod - def from_dict(obj: Any) -> 'KindClass': + def from_dict(obj: Any) -> 'SystemNotification': assert isinstance(obj, dict) - type = KindType(obj.get("type")) + type = SystemNotificationType(obj.get("type")) agent_id = from_union([from_str, from_none], obj.get("agentId")) agent_type = from_union([from_str, from_none], obj.get("agentType")) description = from_union([from_str, from_none], obj.get("description")) prompt = from_union([from_str, from_none], obj.get("prompt")) - status = from_union([KindStatus, from_none], obj.get("status")) + status = from_union([SystemNotificationAgentCompletedStatus, from_none], obj.get("status")) exit_code = from_union([from_float, from_none], obj.get("exitCode")) shell_id = from_union([from_str, from_none], obj.get("shellId")) - return KindClass(type, agent_id, agent_type, description, prompt, status, exit_code, shell_id) + return SystemNotification(type, agent_id, agent_type, description, prompt, status, exit_code, shell_id) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(KindType, self.type) + result["type"] = to_enum(SystemNotificationType, self.type) if self.agent_id is not None: result["agentId"] = from_union([from_str, from_none], self.agent_id) if self.agent_type is not None: @@ -725,7 +725,7 @@ def to_dict(self) -> dict: if self.prompt is not None: result["prompt"] = from_union([from_str, from_none], self.prompt) if self.status is not None: - result["status"] = from_union([lambda x: to_enum(KindStatus, x), from_none], self.status) + result["status"] = from_union([lambda x: to_enum(SystemNotificationAgentCompletedStatus, x), from_none], self.status) if self.exit_code is not None: result["exitCode"] = from_union([to_float, from_none], self.exit_code) if self.shell_id is not None: @@ -734,7 +734,7 @@ def to_dict(self) -> dict: @dataclass -class Metadata: +class SystemMessageMetadata: """Metadata about the prompt template and its construction""" prompt_version: str | None = None @@ -744,11 +744,11 @@ class Metadata: """Template variables used when constructing the prompt""" @staticmethod - def from_dict(obj: Any) -> 'Metadata': + def from_dict(obj: Any) -> 'SystemMessageMetadata': assert isinstance(obj, dict) prompt_version = from_union([from_str, from_none], obj.get("promptVersion")) variables = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("variables")) - return Metadata(prompt_version, variables) + return SystemMessageMetadata(prompt_version, variables) def to_dict(self) -> dict: result: dict = {} @@ -759,7 +759,7 @@ def to_dict(self) -> dict: return result -class Mode(Enum): +class ElicitationRequestedMode(Enum): """Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. """ @@ -768,7 +768,7 @@ class Mode(Enum): @dataclass -class Requests: +class ShutdownModelMetricRequests: """Request count and cost metrics""" cost: float @@ -778,11 +778,11 @@ class Requests: """Total number of API requests made to this model""" @staticmethod - def from_dict(obj: Any) -> 'Requests': + def from_dict(obj: Any) -> 'ShutdownModelMetricRequests': assert isinstance(obj, dict) cost = from_float(obj.get("cost")) count = from_float(obj.get("count")) - return Requests(cost, count) + return ShutdownModelMetricRequests(cost, count) def to_dict(self) -> dict: result: dict = {} @@ -792,7 +792,7 @@ def to_dict(self) -> dict: @dataclass -class Usage: +class ShutdownModelMetricUsage: """Token usage breakdown""" cache_read_tokens: float @@ -807,14 +807,18 @@ class Usage: output_tokens: float """Total output tokens produced across all requests to this model""" + reasoning_tokens: float | None = None + """Total reasoning tokens produced across all requests to this model""" + @staticmethod - def from_dict(obj: Any) -> 'Usage': + def from_dict(obj: Any) -> 'ShutdownModelMetricUsage': assert isinstance(obj, dict) cache_read_tokens = from_float(obj.get("cacheReadTokens")) cache_write_tokens = from_float(obj.get("cacheWriteTokens")) input_tokens = from_float(obj.get("inputTokens")) output_tokens = from_float(obj.get("outputTokens")) - return Usage(cache_read_tokens, cache_write_tokens, input_tokens, output_tokens) + reasoning_tokens = from_union([from_float, from_none], obj.get("reasoningTokens")) + return ShutdownModelMetricUsage(cache_read_tokens, cache_write_tokens, input_tokens, output_tokens, reasoning_tokens) def to_dict(self) -> dict: result: dict = {} @@ -822,32 +826,34 @@ def to_dict(self) -> dict: result["cacheWriteTokens"] = to_float(self.cache_write_tokens) result["inputTokens"] = to_float(self.input_tokens) result["outputTokens"] = to_float(self.output_tokens) + if self.reasoning_tokens is not None: + result["reasoningTokens"] = from_union([to_float, from_none], self.reasoning_tokens) return result @dataclass -class ModelMetric: - requests: Requests +class ShutdownModelMetric: + requests: ShutdownModelMetricRequests """Request count and cost metrics""" - usage: Usage + usage: ShutdownModelMetricUsage """Token usage breakdown""" @staticmethod - def from_dict(obj: Any) -> 'ModelMetric': + def from_dict(obj: Any) -> 'ShutdownModelMetric': assert isinstance(obj, dict) - requests = Requests.from_dict(obj.get("requests")) - usage = Usage.from_dict(obj.get("usage")) - return ModelMetric(requests, usage) + requests = ShutdownModelMetricRequests.from_dict(obj.get("requests")) + usage = ShutdownModelMetricUsage.from_dict(obj.get("usage")) + return ShutdownModelMetric(requests, usage) def to_dict(self) -> dict: result: dict = {} - result["requests"] = to_class(Requests, self.requests) - result["usage"] = to_class(Usage, self.usage) + result["requests"] = to_class(ShutdownModelMetricRequests, self.requests) + result["usage"] = to_class(ShutdownModelMetricUsage, self.usage) return result -class Operation(Enum): +class ChangedOperation(Enum): """The type of operation performed on the plan file Whether the file was newly created or updated @@ -857,7 +863,7 @@ class Operation(Enum): UPDATE = "update" -class PermissionRequestAction(Enum): +class PermissionRequestMemoryAction(Enum): """Whether this is a store or vote memory operation""" STORE = "store" @@ -865,7 +871,7 @@ class PermissionRequestAction(Enum): @dataclass -class PermissionRequestCommand: +class PermissionRequestShellCommand: identifier: str """Command identifier (e.g., executable name)""" @@ -873,11 +879,11 @@ class PermissionRequestCommand: """Whether this command is read-only (no side effects)""" @staticmethod - def from_dict(obj: Any) -> 'PermissionRequestCommand': + def from_dict(obj: Any) -> 'PermissionRequestShellCommand': assert isinstance(obj, dict) identifier = from_str(obj.get("identifier")) read_only = from_bool(obj.get("readOnly")) - return PermissionRequestCommand(identifier, read_only) + return PermissionRequestShellCommand(identifier, read_only) def to_dict(self) -> dict: result: dict = {} @@ -886,14 +892,14 @@ def to_dict(self) -> dict: return result -class Direction(Enum): +class PermissionRequestMemoryDirection(Enum): """Vote direction (vote only)""" DOWNVOTE = "downvote" UPVOTE = "upvote" -class PermissionRequestKind(Enum): +class Kind(Enum): CUSTOM_TOOL = "custom-tool" HOOK = "hook" MCP = "mcp" @@ -905,15 +911,15 @@ class PermissionRequestKind(Enum): @dataclass -class PossibleURL: +class PermissionRequestShellPossibleURL: url: str """URL that may be accessed by the command""" @staticmethod - def from_dict(obj: Any) -> 'PossibleURL': + def from_dict(obj: Any) -> 'PermissionRequestShellPossibleURL': assert isinstance(obj, dict) url = from_str(obj.get("url")) - return PossibleURL(url) + return PermissionRequestShellPossibleURL(url) def to_dict(self) -> dict: result: dict = {} @@ -941,13 +947,13 @@ class PermissionRequest: Hook confirmation permission request """ - kind: PermissionRequestKind + kind: Kind """Permission kind discriminator""" can_offer_session_approval: bool | None = None """Whether the UI can offer session-wide approval for this command pattern""" - commands: list[PermissionRequestCommand] | None = None + commands: list[PermissionRequestShellCommand] | None = None """Parsed command identifiers found in the command text""" full_command_text: str | None = None @@ -968,7 +974,7 @@ class PermissionRequest: possible_paths: list[str] | None = None """File paths that may be read or written by the command""" - possible_urls: list[PossibleURL] | None = None + possible_urls: list[PermissionRequestShellPossibleURL] | None = None """URLs that may be accessed by the command""" tool_call_id: str | None = None @@ -1013,13 +1019,13 @@ class PermissionRequest: url: str | None = None """URL to be fetched""" - action: PermissionRequestAction | None = None + action: PermissionRequestMemoryAction | None = None """Whether this is a store or vote memory operation""" citations: str | None = None """Source references for the stored fact (store only)""" - direction: Direction | None = None + direction: PermissionRequestMemoryDirection | None = None """Vote direction (vote only)""" fact: str | None = None @@ -1043,14 +1049,14 @@ class PermissionRequest: @staticmethod def from_dict(obj: Any) -> 'PermissionRequest': assert isinstance(obj, dict) - kind = PermissionRequestKind(obj.get("kind")) + kind = Kind(obj.get("kind")) can_offer_session_approval = from_union([from_bool, from_none], obj.get("canOfferSessionApproval")) - commands = from_union([lambda x: from_list(PermissionRequestCommand.from_dict, x), from_none], obj.get("commands")) + commands = from_union([lambda x: from_list(PermissionRequestShellCommand.from_dict, x), from_none], obj.get("commands")) full_command_text = from_union([from_str, from_none], obj.get("fullCommandText")) has_write_file_redirection = from_union([from_bool, from_none], obj.get("hasWriteFileRedirection")) intention = from_union([from_str, from_none], obj.get("intention")) possible_paths = from_union([lambda x: from_list(from_str, x), from_none], obj.get("possiblePaths")) - possible_urls = from_union([lambda x: from_list(PossibleURL.from_dict, x), from_none], obj.get("possibleUrls")) + possible_urls = from_union([lambda x: from_list(PermissionRequestShellPossibleURL.from_dict, x), from_none], obj.get("possibleUrls")) tool_call_id = from_union([from_str, from_none], obj.get("toolCallId")) warning = from_union([from_str, from_none], obj.get("warning")) diff = from_union([from_str, from_none], obj.get("diff")) @@ -1063,9 +1069,9 @@ def from_dict(obj: Any) -> 'PermissionRequest': tool_name = from_union([from_str, from_none], obj.get("toolName")) tool_title = from_union([from_str, from_none], obj.get("toolTitle")) url = from_union([from_str, from_none], obj.get("url")) - action = from_union([PermissionRequestAction, from_none], obj.get("action")) + action = from_union([PermissionRequestMemoryAction, from_none], obj.get("action")) citations = from_union([from_str, from_none], obj.get("citations")) - direction = from_union([Direction, from_none], obj.get("direction")) + direction = from_union([PermissionRequestMemoryDirection, from_none], obj.get("direction")) fact = from_union([from_str, from_none], obj.get("fact")) reason = from_union([from_str, from_none], obj.get("reason")) subject = from_union([from_str, from_none], obj.get("subject")) @@ -1076,11 +1082,11 @@ def from_dict(obj: Any) -> 'PermissionRequest': def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionRequestKind, self.kind) + result["kind"] = to_enum(Kind, self.kind) if self.can_offer_session_approval is not None: result["canOfferSessionApproval"] = from_union([from_bool, from_none], self.can_offer_session_approval) if self.commands is not None: - result["commands"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRequestCommand, x), x), from_none], self.commands) + result["commands"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRequestShellCommand, x), x), from_none], self.commands) if self.full_command_text is not None: result["fullCommandText"] = from_union([from_str, from_none], self.full_command_text) if self.has_write_file_redirection is not None: @@ -1090,7 +1096,7 @@ def to_dict(self) -> dict: if self.possible_paths is not None: result["possiblePaths"] = from_union([lambda x: from_list(from_str, x), from_none], self.possible_paths) if self.possible_urls is not None: - result["possibleUrls"] = from_union([lambda x: from_list(lambda x: to_class(PossibleURL, x), x), from_none], self.possible_urls) + result["possibleUrls"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRequestShellPossibleURL, x), x), from_none], self.possible_urls) if self.tool_call_id is not None: result["toolCallId"] = from_union([from_str, from_none], self.tool_call_id) if self.warning is not None: @@ -1116,11 +1122,11 @@ def to_dict(self) -> dict: if self.url is not None: result["url"] = from_union([from_str, from_none], self.url) if self.action is not None: - result["action"] = from_union([lambda x: to_enum(PermissionRequestAction, x), from_none], self.action) + result["action"] = from_union([lambda x: to_enum(PermissionRequestMemoryAction, x), from_none], self.action) if self.citations is not None: result["citations"] = from_union([from_str, from_none], self.citations) if self.direction is not None: - result["direction"] = from_union([lambda x: to_enum(Direction, x), from_none], self.direction) + result["direction"] = from_union([lambda x: to_enum(PermissionRequestMemoryDirection, x), from_none], self.direction) if self.fact is not None: result["fact"] = from_union([from_str, from_none], self.fact) if self.reason is not None: @@ -1137,7 +1143,7 @@ def to_dict(self) -> dict: @dataclass -class QuotaSnapshot: +class AssistantUsageQuotaSnapshot: entitlement_requests: float """Total requests allowed by the entitlement""" @@ -1163,7 +1169,7 @@ class QuotaSnapshot: """Date when the quota resets""" @staticmethod - def from_dict(obj: Any) -> 'QuotaSnapshot': + def from_dict(obj: Any) -> 'AssistantUsageQuotaSnapshot': assert isinstance(obj, dict) entitlement_requests = from_float(obj.get("entitlementRequests")) is_unlimited_entitlement = from_bool(obj.get("isUnlimitedEntitlement")) @@ -1173,7 +1179,7 @@ def from_dict(obj: Any) -> 'QuotaSnapshot': usage_allowed_with_exhausted_quota = from_bool(obj.get("usageAllowedWithExhaustedQuota")) used_requests = from_float(obj.get("usedRequests")) reset_date = from_union([from_datetime, from_none], obj.get("resetDate")) - return QuotaSnapshot(entitlement_requests, is_unlimited_entitlement, overage, overage_allowed_with_exhausted_quota, remaining_percentage, usage_allowed_with_exhausted_quota, used_requests, reset_date) + return AssistantUsageQuotaSnapshot(entitlement_requests, is_unlimited_entitlement, overage, overage_allowed_with_exhausted_quota, remaining_percentage, usage_allowed_with_exhausted_quota, used_requests, reset_date) def to_dict(self) -> dict: result: dict = {} @@ -1190,7 +1196,7 @@ def to_dict(self) -> dict: @dataclass -class RepositoryClass: +class HandoffRepository: """Repository context for the handed-off session""" name: str @@ -1203,12 +1209,12 @@ class RepositoryClass: """Git branch name, if applicable""" @staticmethod - def from_dict(obj: Any) -> 'RepositoryClass': + def from_dict(obj: Any) -> 'HandoffRepository': assert isinstance(obj, dict) name = from_str(obj.get("name")) owner = from_str(obj.get("owner")) branch = from_union([from_str, from_none], obj.get("branch")) - return RepositoryClass(name, owner, branch) + return HandoffRepository(name, owner, branch) def to_dict(self) -> dict: result: dict = {} @@ -1224,7 +1230,7 @@ class RequestedSchemaType(Enum): @dataclass -class RequestedSchema: +class ElicitationRequestedSchema: """JSON Schema describing the form fields to present to the user (form mode only)""" properties: dict[str, Any] @@ -1237,12 +1243,12 @@ class RequestedSchema: """List of required field names""" @staticmethod - def from_dict(obj: Any) -> 'RequestedSchema': + def from_dict(obj: Any) -> 'ElicitationRequestedSchema': assert isinstance(obj, dict) properties = from_dict(lambda x: x, obj.get("properties")) type = RequestedSchemaType(obj.get("type")) required = from_union([lambda x: from_list(from_str, x), from_none], obj.get("required")) - return RequestedSchema(properties, type, required) + return ElicitationRequestedSchema(properties, type, required) def to_dict(self) -> dict: result: dict = {} @@ -1253,7 +1259,7 @@ def to_dict(self) -> dict: return result -class Theme(Enum): +class ToolExecutionCompleteContentResourceLinkIconTheme(Enum): """Theme variant this icon is intended for""" DARK = "dark" @@ -1261,7 +1267,7 @@ class Theme(Enum): @dataclass -class Icon: +class ToolExecutionCompleteContentResourceLinkIcon: """Icon image for a resource""" src: str @@ -1273,17 +1279,17 @@ class Icon: sizes: list[str] | None = None """Available icon sizes (e.g., ['16x16', '32x32'])""" - theme: Theme | None = None + theme: ToolExecutionCompleteContentResourceLinkIconTheme | None = None """Theme variant this icon is intended for""" @staticmethod - def from_dict(obj: Any) -> 'Icon': + def from_dict(obj: Any) -> 'ToolExecutionCompleteContentResourceLinkIcon': assert isinstance(obj, dict) src = from_str(obj.get("src")) mime_type = from_union([from_str, from_none], obj.get("mimeType")) sizes = from_union([lambda x: from_list(from_str, x), from_none], obj.get("sizes")) - theme = from_union([Theme, from_none], obj.get("theme")) - return Icon(src, mime_type, sizes, theme) + theme = from_union([ToolExecutionCompleteContentResourceLinkIconTheme, from_none], obj.get("theme")) + return ToolExecutionCompleteContentResourceLinkIcon(src, mime_type, sizes, theme) def to_dict(self) -> dict: result: dict = {} @@ -1293,12 +1299,12 @@ def to_dict(self) -> dict: if self.sizes is not None: result["sizes"] = from_union([lambda x: from_list(from_str, x), from_none], self.sizes) if self.theme is not None: - result["theme"] = from_union([lambda x: to_enum(Theme, x), from_none], self.theme) + result["theme"] = from_union([lambda x: to_enum(ToolExecutionCompleteContentResourceLinkIconTheme, x), from_none], self.theme) return result @dataclass -class Resource: +class ToolExecutionCompleteContentResourceDetails: """The embedded resource contents, either text or base64-encoded binary""" uri: str @@ -1316,13 +1322,13 @@ class Resource: """Base64-encoded binary content of the resource""" @staticmethod - def from_dict(obj: Any) -> 'Resource': + def from_dict(obj: Any) -> 'ToolExecutionCompleteContentResourceDetails': assert isinstance(obj, dict) uri = from_str(obj.get("uri")) mime_type = from_union([from_str, from_none], obj.get("mimeType")) text = from_union([from_str, from_none], obj.get("text")) blob = from_union([from_str, from_none], obj.get("blob")) - return Resource(uri, mime_type, text, blob) + return ToolExecutionCompleteContentResourceDetails(uri, mime_type, text, blob) def to_dict(self) -> dict: result: dict = {} @@ -1336,7 +1342,7 @@ def to_dict(self) -> dict: return result -class ContentType(Enum): +class ToolExecutionCompleteContentType(Enum): AUDIO = "audio" IMAGE = "image" RESOURCE = "resource" @@ -1346,7 +1352,7 @@ class ContentType(Enum): @dataclass -class ContentElement: +class ToolExecutionCompleteContent: """A content block within a tool result, which may be text, terminal output, image, audio, or a resource @@ -1362,7 +1368,7 @@ class ContentElement: Embedded resource content block with inline text or binary data """ - type: ContentType + type: ToolExecutionCompleteContentType """Content block type discriminator""" text: str | None = None @@ -1391,7 +1397,7 @@ class ContentElement: description: str | None = None """Human-readable description of the resource""" - icons: list[Icon] | None = None + icons: list[ToolExecutionCompleteContentResourceLinkIcon] | None = None """Icons associated with this resource""" name: str | None = None @@ -1406,30 +1412,30 @@ class ContentElement: uri: str | None = None """URI identifying the resource""" - resource: Resource | None = None + resource: ToolExecutionCompleteContentResourceDetails | None = None """The embedded resource contents, either text or base64-encoded binary""" @staticmethod - def from_dict(obj: Any) -> 'ContentElement': + def from_dict(obj: Any) -> 'ToolExecutionCompleteContent': assert isinstance(obj, dict) - type = ContentType(obj.get("type")) + type = ToolExecutionCompleteContentType(obj.get("type")) text = from_union([from_str, from_none], obj.get("text")) cwd = from_union([from_str, from_none], obj.get("cwd")) exit_code = from_union([from_float, from_none], obj.get("exitCode")) data = from_union([from_str, from_none], obj.get("data")) mime_type = from_union([from_str, from_none], obj.get("mimeType")) description = from_union([from_str, from_none], obj.get("description")) - icons = from_union([lambda x: from_list(Icon.from_dict, x), from_none], obj.get("icons")) + icons = from_union([lambda x: from_list(ToolExecutionCompleteContentResourceLinkIcon.from_dict, x), from_none], obj.get("icons")) name = from_union([from_str, from_none], obj.get("name")) size = from_union([from_float, from_none], obj.get("size")) title = from_union([from_str, from_none], obj.get("title")) uri = from_union([from_str, from_none], obj.get("uri")) - resource = from_union([Resource.from_dict, from_none], obj.get("resource")) - return ContentElement(type, text, cwd, exit_code, data, mime_type, description, icons, name, size, title, uri, resource) + resource = from_union([ToolExecutionCompleteContentResourceDetails.from_dict, from_none], obj.get("resource")) + return ToolExecutionCompleteContent(type, text, cwd, exit_code, data, mime_type, description, icons, name, size, title, uri, resource) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(ContentType, self.type) + result["type"] = to_enum(ToolExecutionCompleteContentType, self.type) if self.text is not None: result["text"] = from_union([from_str, from_none], self.text) if self.cwd is not None: @@ -1443,7 +1449,7 @@ def to_dict(self) -> dict: if self.description is not None: result["description"] = from_union([from_str, from_none], self.description) if self.icons is not None: - result["icons"] = from_union([lambda x: from_list(lambda x: to_class(Icon, x), x), from_none], self.icons) + result["icons"] = from_union([lambda x: from_list(lambda x: to_class(ToolExecutionCompleteContentResourceLinkIcon, x), x), from_none], self.icons) if self.name is not None: result["name"] = from_union([from_str, from_none], self.name) if self.size is not None: @@ -1453,11 +1459,11 @@ def to_dict(self) -> dict: if self.uri is not None: result["uri"] = from_union([from_str, from_none], self.uri) if self.resource is not None: - result["resource"] = from_union([lambda x: to_class(Resource, x), from_none], self.resource) + result["resource"] = from_union([lambda x: to_class(ToolExecutionCompleteContentResourceDetails, x), from_none], self.resource) return result -class ResultKind(Enum): +class PermissionCompletedKind(Enum): """The outcome of the permission request""" APPROVED = "approved" @@ -1478,7 +1484,7 @@ class Result: """Concise tool result text sent to the LLM for chat completion, potentially truncated for token efficiency """ - contents: list[ContentElement] | None = None + contents: list[ToolExecutionCompleteContent] | None = None """Structured content blocks (text, images, audio, resources) returned by the tool in their native format """ @@ -1486,16 +1492,16 @@ class Result: """Full detailed tool result for UI/timeline display, preserving complete content such as diffs. Falls back to content when absent. """ - kind: ResultKind | None = None + kind: PermissionCompletedKind | None = None """The outcome of the permission request""" @staticmethod def from_dict(obj: Any) -> 'Result': assert isinstance(obj, dict) content = from_union([from_str, from_none], obj.get("content")) - contents = from_union([lambda x: from_list(ContentElement.from_dict, x), from_none], obj.get("contents")) + contents = from_union([lambda x: from_list(ToolExecutionCompleteContent.from_dict, x), from_none], obj.get("contents")) detailed_content = from_union([from_str, from_none], obj.get("detailedContent")) - kind = from_union([ResultKind, from_none], obj.get("kind")) + kind = from_union([PermissionCompletedKind, from_none], obj.get("kind")) return Result(content, contents, detailed_content, kind) def to_dict(self) -> dict: @@ -1503,22 +1509,22 @@ def to_dict(self) -> dict: if self.content is not None: result["content"] = from_union([from_str, from_none], self.content) if self.contents is not None: - result["contents"] = from_union([lambda x: from_list(lambda x: to_class(ContentElement, x), x), from_none], self.contents) + result["contents"] = from_union([lambda x: from_list(lambda x: to_class(ToolExecutionCompleteContent, x), x), from_none], self.contents) if self.detailed_content is not None: result["detailedContent"] = from_union([from_str, from_none], self.detailed_content) if self.kind is not None: - result["kind"] = from_union([lambda x: to_enum(ResultKind, x), from_none], self.kind) + result["kind"] = from_union([lambda x: to_enum(PermissionCompletedKind, x), from_none], self.kind) return result -class Role(Enum): +class SystemMessageRole(Enum): """Message role: "system" for system prompts, "developer" for developer-injected instructions""" DEVELOPER = "developer" SYSTEM = "system" -class ServerStatus(Enum): +class MCPServerStatus(Enum): """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured New connection status: connected, failed, needs-auth, pending, disabled, or not_configured @@ -1532,11 +1538,11 @@ class ServerStatus(Enum): @dataclass -class Server: +class MCPServersLoadedServer: name: str """Server name (config key)""" - status: ServerStatus + status: MCPServerStatus """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" error: str | None = None @@ -1546,18 +1552,18 @@ class Server: """Configuration source: user, workspace, plugin, or builtin""" @staticmethod - def from_dict(obj: Any) -> 'Server': + def from_dict(obj: Any) -> 'MCPServersLoadedServer': assert isinstance(obj, dict) name = from_str(obj.get("name")) - status = ServerStatus(obj.get("status")) + status = MCPServerStatus(obj.get("status")) error = from_union([from_str, from_none], obj.get("error")) source = from_union([from_str, from_none], obj.get("source")) - return Server(name, status, error, source) + return MCPServersLoadedServer(name, status, error, source) def to_dict(self) -> dict: result: dict = {} result["name"] = from_str(self.name) - result["status"] = to_enum(ServerStatus, self.status) + result["status"] = to_enum(MCPServerStatus, self.status) if self.error is not None: result["error"] = from_union([from_str, from_none], self.error) if self.source is not None: @@ -1573,7 +1579,7 @@ class ShutdownType(Enum): @dataclass -class Skill: +class SkillsLoadedSkill: description: str """Description of what the skill does""" @@ -1593,7 +1599,7 @@ class Skill: """Absolute path to the skill file, if available""" @staticmethod - def from_dict(obj: Any) -> 'Skill': + def from_dict(obj: Any) -> 'SkillsLoadedSkill': assert isinstance(obj, dict) description = from_str(obj.get("description")) enabled = from_bool(obj.get("enabled")) @@ -1601,7 +1607,7 @@ def from_dict(obj: Any) -> 'Skill': source = from_str(obj.get("source")) user_invocable = from_bool(obj.get("userInvocable")) path = from_union([from_str, from_none], obj.get("path")) - return Skill(description, enabled, name, source, user_invocable, path) + return SkillsLoadedSkill(description, enabled, name, source, user_invocable, path) def to_dict(self) -> dict: result: dict = {} @@ -1615,7 +1621,7 @@ def to_dict(self) -> dict: return result -class SourceType(Enum): +class HandoffSourceType(Enum): """Origin type of the session being handed off""" LOCAL = "local" @@ -1623,7 +1629,7 @@ class SourceType(Enum): @dataclass -class StaticClientConfig: +class MCPOauthRequiredStaticClientConfig: """Static OAuth client configuration, if the server specifies one""" client_id: str @@ -1633,11 +1639,11 @@ class StaticClientConfig: """Whether this is a public OAuth client""" @staticmethod - def from_dict(obj: Any) -> 'StaticClientConfig': + def from_dict(obj: Any) -> 'MCPOauthRequiredStaticClientConfig': assert isinstance(obj, dict) client_id = from_str(obj.get("clientId")) public_client = from_union([from_bool, from_none], obj.get("publicClient")) - return StaticClientConfig(client_id, public_client) + return MCPOauthRequiredStaticClientConfig(client_id, public_client) def to_dict(self) -> dict: result: dict = {} @@ -1647,7 +1653,7 @@ def to_dict(self) -> dict: return result -class ToolRequestType(Enum): +class AssistantMessageToolRequestType(Enum): """Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. """ @@ -1656,7 +1662,7 @@ class ToolRequestType(Enum): @dataclass -class ToolRequest: +class AssistantMessageToolRequest: """A tool invocation request from the assistant""" name: str @@ -1677,13 +1683,13 @@ class ToolRequest: tool_title: str | None = None """Human-readable display title for the tool""" - type: ToolRequestType | None = None + type: AssistantMessageToolRequestType | None = None """Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. """ @staticmethod - def from_dict(obj: Any) -> 'ToolRequest': + def from_dict(obj: Any) -> 'AssistantMessageToolRequest': assert isinstance(obj, dict) name = from_str(obj.get("name")) tool_call_id = from_str(obj.get("toolCallId")) @@ -1691,8 +1697,8 @@ def from_dict(obj: Any) -> 'ToolRequest': 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, mcp_server_name, tool_title, type) + type = from_union([AssistantMessageToolRequestType, from_none], obj.get("type")) + return AssistantMessageToolRequest(name, tool_call_id, arguments, intention_summary, mcp_server_name, tool_title, type) def to_dict(self) -> dict: result: dict = {} @@ -1707,22 +1713,22 @@ def to_dict(self) -> dict: if self.tool_title is not None: result["toolTitle"] = from_union([from_str, from_none], self.tool_title) if self.type is not None: - result["type"] = from_union([lambda x: to_enum(ToolRequestType, x), from_none], self.type) + result["type"] = from_union([lambda x: to_enum(AssistantMessageToolRequestType, x), from_none], self.type) return result @dataclass -class UI: +class CapabilitiesChangedUI: """UI capability changes""" elicitation: bool | None = None """Whether elicitation is now supported""" @staticmethod - def from_dict(obj: Any) -> 'UI': + def from_dict(obj: Any) -> 'CapabilitiesChangedUI': assert isinstance(obj, dict) elicitation = from_union([from_bool, from_none], obj.get("elicitation")) - return UI(elicitation) + return CapabilitiesChangedUI(elicitation) def to_dict(self) -> dict: result: dict = {} @@ -1878,7 +1884,7 @@ class Data: Whether the session was already in use by another client at resume time """ - context: ContextClass | str | None = None + context: Context | str | None = None """Working directory and git context at session start Updated working directory and git context at resume time @@ -1986,7 +1992,7 @@ class Data: previous_mode: str | None = None """Agent mode before the change (e.g., "interactive", "plan", "autopilot")""" - operation: Operation | None = None + operation: ChangedOperation | None = None """The type of operation performed on the plan file Whether the file was newly created or updated @@ -2006,13 +2012,13 @@ class Data: remote_session_id: str | None = None """Session ID of the remote session being handed off""" - repository: RepositoryClass | str | None = None + repository: HandoffRepository | str | None = None """Repository context for the handed-off session Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) """ - source_type: SourceType | None = None + source_type: HandoffSourceType | None = None """Origin type of the session being handed off""" summary: str | None = None @@ -2052,7 +2058,7 @@ class Data: up_to_event_id: str | None = None """Event ID that was rewound to; this event and all after it were removed""" - code_changes: CodeChanges | None = None + code_changes: ShutdownCodeChanges | None = None """Aggregate code change metrics for the session""" conversation_tokens: float | None = None @@ -2075,7 +2081,7 @@ class Data: error_reason: str | None = None """Error description when shutdownType is "error\"""" - model_metrics: dict[str, ModelMetric] | None = None + model_metrics: dict[str, ShutdownModelMetric] | None = None """Per-model usage breakdown, keyed by model identifier""" session_start_time: float | None = None @@ -2123,7 +2129,7 @@ class Data: head_commit: str | None = None """Head commit of current git branch at session start time""" - host_type: HostType | None = None + host_type: ContextChangedHostType | None = None """Hosting platform type of the repository (github or ado)""" is_initial: bool | None = None @@ -2138,10 +2144,10 @@ class Data: checkpoint_path: str | None = None """File path where the checkpoint was stored""" - compaction_tokens_used: CompactionTokensUsed | None = None + compaction_tokens_used: CompactionCompleteCompactionTokensUsed | None = None """Token usage breakdown for the compaction LLM call""" - error: ErrorClass | str | None = None + error: Error | str | None = None """Error message if compaction failed Error details when the tool execution failed @@ -2229,10 +2235,10 @@ class Data: tokens_removed: float | None = None """Number of tokens removed during compaction""" - agent_mode: AgentMode | None = None + agent_mode: UserMessageAgentMode | None = None """The agent mode that was active when this message was sent""" - attachments: list[Attachment] | None = None + attachments: list[UserMessageAttachment] | None = None """Files, selections, or GitHub references attached to the message""" content: str | dict[str, float | bool | list[str] | str] | None = None @@ -2319,7 +2325,7 @@ class Data: reasoning_text: str | None = None """Readable reasoning text from the model's extended thinking""" - tool_requests: list[ToolRequest] | None = None + tool_requests: list[AssistantMessageToolRequest] | None = None """Tool invocations requested by the assistant in this message""" api_call_id: str | None = None @@ -2331,7 +2337,7 @@ class Data: cache_write_tokens: float | None = None """Number of tokens written to prompt cache""" - copilot_usage: CopilotUsage | None = None + copilot_usage: AssistantUsageCopilotUsage | None = None """Per-request cost and usage data from the CAPI copilot_usage response field""" cost: float | None = None @@ -2359,9 +2365,12 @@ class Data: Model used by the sub-agent (if any model calls succeeded before failure) """ - quota_snapshots: dict[str, QuotaSnapshot] | None = None + quota_snapshots: dict[str, AssistantUsageQuotaSnapshot] | None = None """Per-quota resource usage snapshots, keyed by quota identifier""" + reasoning_tokens: float | None = None + """Number of output tokens used for reasoning (e.g., chain-of-thought)""" + ttft_ms: float | None = None """Time to first token in milliseconds. Only available for streaming requests""" @@ -2486,13 +2495,13 @@ class Data: output: Any = None """Output data produced by the hook""" - metadata: Metadata | None = None + metadata: SystemMessageMetadata | None = None """Metadata about the prompt template and its construction""" - role: Role | None = None + role: SystemMessageRole | None = None """Message role: "system" for system prompts, "developer" for developer-injected instructions""" - kind: KindClass | None = None + kind: SystemNotification | None = None """Structured metadata identifying what triggered this notification""" permission_request: PermissionRequest | None = None @@ -2520,14 +2529,14 @@ class Data: elicitation_source: str | None = None """The source that initiated the request (MCP server name, or absent for agent-initiated)""" - mode: Mode | None = None + mode: ElicitationRequestedMode | None = None """Elicitation mode; "form" for structured input, "url" for browser-based. Defaults to "form" when absent. """ - requested_schema: RequestedSchema | None = None + requested_schema: ElicitationRequestedSchema | None = None """JSON Schema describing the form fields to present to the user (form mode only)""" - action: DataAction | None = None + action: ElicitationCompletedAction | None = None """The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) """ @@ -2544,7 +2553,7 @@ class Data: server_url: str | None = None """URL of the MCP server that requires OAuth""" - static_client_config: StaticClientConfig | None = None + static_client_config: MCPOauthRequiredStaticClientConfig | None = None """Static OAuth client configuration, if the server specifies one""" traceparent: str | None = None @@ -2564,10 +2573,10 @@ class Data: command_name: str | None = None """Command name without leading /""" - commands: list[DataCommand] | None = None + commands: list[CommandsChangedCommand] | None = None """Current list of registered SDK commands""" - ui: UI | None = None + ui: CapabilitiesChangedUI | None = None """UI capability changes""" actions: list[str] | None = None @@ -2591,10 +2600,10 @@ class Data: selected_action: str | None = None """Which action the user selected (e.g. 'autopilot', 'interactive', 'exit_only')""" - skills: list[Skill] | None = None + skills: list[SkillsLoadedSkill] | None = None """Array of resolved skill metadata""" - agents: list[Agent] | None = None + agents: list[CustomAgentsUpdatedAgent] | None = None """Array of loaded custom agent metadata""" errors: list[str] | None = None @@ -2603,20 +2612,20 @@ class Data: warnings: list[str] | None = None """Non-fatal warnings from agent loading""" - servers: list[Server] | None = None + servers: list[MCPServersLoadedServer] | None = None """Array of MCP server status summaries""" - status: ServerStatus | None = None + status: MCPServerStatus | None = None """New connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" - extensions: list[Extension] | None = None + extensions: list[ExtensionsLoadedExtension] | None = None """Array of discovered extensions and their status""" @staticmethod def from_dict(obj: Any) -> 'Data': assert isinstance(obj, dict) already_in_use = from_union([from_bool, from_none], obj.get("alreadyInUse")) - context = from_union([ContextClass.from_dict, from_str, from_none], obj.get("context")) + context = from_union([Context.from_dict, from_str, from_none], obj.get("context")) copilot_version = from_union([from_str, from_none], obj.get("copilotVersion")) producer = from_union([from_str, from_none], obj.get("producer")) reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort")) @@ -2642,13 +2651,13 @@ def from_dict(obj: Any) -> 'Data': previous_reasoning_effort = from_union([from_str, from_none], obj.get("previousReasoningEffort")) new_mode = from_union([from_str, from_none], obj.get("newMode")) previous_mode = from_union([from_str, from_none], obj.get("previousMode")) - operation = from_union([Operation, from_none], obj.get("operation")) + operation = from_union([ChangedOperation, from_none], obj.get("operation")) path = from_union([from_str, from_none], obj.get("path")) handoff_time = from_union([from_datetime, from_none], obj.get("handoffTime")) host = from_union([from_str, from_none], obj.get("host")) remote_session_id = from_union([from_str, from_none], obj.get("remoteSessionId")) - repository = from_union([RepositoryClass.from_dict, from_str, from_none], obj.get("repository")) - source_type = from_union([SourceType, from_none], obj.get("sourceType")) + repository = from_union([HandoffRepository.from_dict, from_str, from_none], obj.get("repository")) + source_type = from_union([HandoffSourceType, from_none], obj.get("sourceType")) summary = from_union([from_str, from_none], obj.get("summary")) messages_removed_during_truncation = from_union([from_float, from_none], obj.get("messagesRemovedDuringTruncation")) performed_by = from_union([from_str, from_none], obj.get("performedBy")) @@ -2660,12 +2669,12 @@ def from_dict(obj: Any) -> 'Data': tokens_removed_during_truncation = from_union([from_float, from_none], obj.get("tokensRemovedDuringTruncation")) events_removed = from_union([from_float, from_none], obj.get("eventsRemoved")) up_to_event_id = from_union([from_str, from_none], obj.get("upToEventId")) - code_changes = from_union([CodeChanges.from_dict, from_none], obj.get("codeChanges")) + code_changes = from_union([ShutdownCodeChanges.from_dict, from_none], obj.get("codeChanges")) conversation_tokens = from_union([from_float, from_none], obj.get("conversationTokens")) current_model = from_union([from_str, from_none], obj.get("currentModel")) current_tokens = from_union([from_float, from_none], obj.get("currentTokens")) error_reason = from_union([from_str, from_none], obj.get("errorReason")) - model_metrics = from_union([lambda x: from_dict(ModelMetric.from_dict, x), from_none], obj.get("modelMetrics")) + model_metrics = from_union([lambda x: from_dict(ShutdownModelMetric.from_dict, x), from_none], obj.get("modelMetrics")) session_start_time = from_union([from_float, from_none], obj.get("sessionStartTime")) shutdown_type = from_union([ShutdownType, from_none], obj.get("shutdownType")) system_tokens = from_union([from_float, from_none], obj.get("systemTokens")) @@ -2677,13 +2686,13 @@ def from_dict(obj: Any) -> 'Data': cwd = from_union([from_str, from_none], obj.get("cwd")) git_root = from_union([from_str, from_none], obj.get("gitRoot")) head_commit = from_union([from_str, from_none], obj.get("headCommit")) - host_type = from_union([HostType, from_none], obj.get("hostType")) + host_type = from_union([ContextChangedHostType, from_none], obj.get("hostType")) is_initial = from_union([from_bool, from_none], obj.get("isInitial")) messages_length = from_union([from_float, from_none], obj.get("messagesLength")) checkpoint_number = from_union([from_float, from_none], obj.get("checkpointNumber")) checkpoint_path = from_union([from_str, from_none], obj.get("checkpointPath")) - compaction_tokens_used = from_union([CompactionTokensUsed.from_dict, from_none], obj.get("compactionTokensUsed")) - error = from_union([ErrorClass.from_dict, from_str, from_none], obj.get("error")) + compaction_tokens_used = from_union([CompactionCompleteCompactionTokensUsed.from_dict, from_none], obj.get("compactionTokensUsed")) + error = from_union([Error.from_dict, from_str, from_none], obj.get("error")) messages_removed = from_union([from_float, from_none], obj.get("messagesRemoved")) post_compaction_tokens = from_union([from_float, from_none], obj.get("postCompactionTokens")) pre_compaction_messages_length = from_union([from_float, from_none], obj.get("preCompactionMessagesLength")) @@ -2692,8 +2701,8 @@ def from_dict(obj: Any) -> 'Data': success = from_union([from_bool, from_none], obj.get("success")) summary_content = from_union([from_str, from_none], obj.get("summaryContent")) tokens_removed = from_union([from_float, from_none], obj.get("tokensRemoved")) - agent_mode = from_union([AgentMode, from_none], obj.get("agentMode")) - attachments = from_union([lambda x: from_list(Attachment.from_dict, x), from_none], obj.get("attachments")) + agent_mode = from_union([UserMessageAgentMode, from_none], obj.get("agentMode")) + attachments = from_union([lambda x: from_list(UserMessageAttachment.from_dict, x), from_none], obj.get("attachments")) content = from_union([from_str, lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) interaction_id = from_union([from_str, from_none], obj.get("interactionId")) source = from_union([from_str, from_none], obj.get("source")) @@ -2710,18 +2719,19 @@ def from_dict(obj: Any) -> 'Data': phase = from_union([from_str, from_none], obj.get("phase")) reasoning_opaque = from_union([from_str, from_none], obj.get("reasoningOpaque")) reasoning_text = from_union([from_str, from_none], obj.get("reasoningText")) - tool_requests = from_union([lambda x: from_list(ToolRequest.from_dict, x), from_none], obj.get("toolRequests")) + tool_requests = from_union([lambda x: from_list(AssistantMessageToolRequest.from_dict, x), from_none], obj.get("toolRequests")) api_call_id = from_union([from_str, from_none], obj.get("apiCallId")) cache_read_tokens = from_union([from_float, from_none], obj.get("cacheReadTokens")) cache_write_tokens = from_union([from_float, from_none], obj.get("cacheWriteTokens")) - copilot_usage = from_union([CopilotUsage.from_dict, from_none], obj.get("copilotUsage")) + copilot_usage = from_union([AssistantUsageCopilotUsage.from_dict, from_none], obj.get("copilotUsage")) cost = from_union([from_float, from_none], obj.get("cost")) duration = from_union([from_float, from_none], obj.get("duration")) initiator = from_union([from_str, from_none], obj.get("initiator")) input_tokens = from_union([from_float, from_none], obj.get("inputTokens")) inter_token_latency_ms = from_union([from_float, from_none], obj.get("interTokenLatencyMs")) model = from_union([from_str, from_none], obj.get("model")) - quota_snapshots = from_union([lambda x: from_dict(QuotaSnapshot.from_dict, x), from_none], obj.get("quotaSnapshots")) + quota_snapshots = from_union([lambda x: from_dict(AssistantUsageQuotaSnapshot.from_dict, x), from_none], obj.get("quotaSnapshots")) + reasoning_tokens = from_union([from_float, from_none], obj.get("reasoningTokens")) ttft_ms = from_union([from_float, from_none], obj.get("ttftMs")) reason = from_union([from_str, from_none], obj.get("reason")) arguments = obj.get("arguments") @@ -2750,9 +2760,9 @@ def from_dict(obj: Any) -> 'Data': hook_type = from_union([from_str, from_none], obj.get("hookType")) input = obj.get("input") output = obj.get("output") - metadata = from_union([Metadata.from_dict, from_none], obj.get("metadata")) - role = from_union([Role, from_none], obj.get("role")) - kind = from_union([KindClass.from_dict, from_none], obj.get("kind")) + metadata = from_union([SystemMessageMetadata.from_dict, from_none], obj.get("metadata")) + role = from_union([SystemMessageRole, from_none], obj.get("role")) + kind = from_union([SystemNotification.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")) @@ -2761,20 +2771,20 @@ def from_dict(obj: Any) -> 'Data': answer = from_union([from_str, from_none], obj.get("answer")) was_freeform = from_union([from_bool, from_none], obj.get("wasFreeform")) elicitation_source = from_union([from_str, from_none], obj.get("elicitationSource")) - mode = from_union([Mode, from_none], obj.get("mode")) - requested_schema = from_union([RequestedSchema.from_dict, from_none], obj.get("requestedSchema")) - action = from_union([DataAction, from_none], obj.get("action")) + mode = from_union([ElicitationRequestedMode, from_none], obj.get("mode")) + requested_schema = from_union([ElicitationRequestedSchema.from_dict, from_none], obj.get("requestedSchema")) + action = from_union([ElicitationCompletedAction, from_none], obj.get("action")) mcp_request_id = from_union([from_float, from_str, from_none], obj.get("mcpRequestId")) server_name = from_union([from_str, from_none], obj.get("serverName")) server_url = from_union([from_str, from_none], obj.get("serverUrl")) - static_client_config = from_union([StaticClientConfig.from_dict, from_none], obj.get("staticClientConfig")) + static_client_config = from_union([MCPOauthRequiredStaticClientConfig.from_dict, from_none], obj.get("staticClientConfig")) traceparent = from_union([from_str, from_none], obj.get("traceparent")) tracestate = from_union([from_str, from_none], obj.get("tracestate")) command = from_union([from_str, from_none], obj.get("command")) args = from_union([from_str, from_none], obj.get("args")) command_name = from_union([from_str, from_none], obj.get("commandName")) - commands = from_union([lambda x: from_list(DataCommand.from_dict, x), from_none], obj.get("commands")) - ui = from_union([UI.from_dict, from_none], obj.get("ui")) + commands = from_union([lambda x: from_list(CommandsChangedCommand.from_dict, x), from_none], obj.get("commands")) + ui = from_union([CapabilitiesChangedUI.from_dict, from_none], obj.get("ui")) actions = from_union([lambda x: from_list(from_str, x), from_none], obj.get("actions")) plan_content = from_union([from_str, from_none], obj.get("planContent")) recommended_action = from_union([from_str, from_none], obj.get("recommendedAction")) @@ -2782,21 +2792,21 @@ def from_dict(obj: Any) -> 'Data': auto_approve_edits = from_union([from_bool, from_none], obj.get("autoApproveEdits")) feedback = from_union([from_str, from_none], obj.get("feedback")) selected_action = from_union([from_str, from_none], obj.get("selectedAction")) - skills = from_union([lambda x: from_list(Skill.from_dict, x), from_none], obj.get("skills")) - agents = from_union([lambda x: from_list(Agent.from_dict, x), from_none], obj.get("agents")) + skills = from_union([lambda x: from_list(SkillsLoadedSkill.from_dict, x), from_none], obj.get("skills")) + agents = from_union([lambda x: from_list(CustomAgentsUpdatedAgent.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, remote_steerable, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, provider_call_id, stack, status_code, url, aborted, 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, answer, was_freeform, elicitation_source, mode, requested_schema, action, mcp_request_id, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, ui, actions, plan_content, recommended_action, approved, auto_approve_edits, feedback, selected_action, skills, agents, errors, warnings, servers, status, extensions) + servers = from_union([lambda x: from_list(MCPServersLoadedServer.from_dict, x), from_none], obj.get("servers")) + status = from_union([MCPServerStatus, from_none], obj.get("status")) + extensions = from_union([lambda x: from_list(ExtensionsLoadedExtension.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, 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, reasoning_tokens, 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, answer, was_freeform, elicitation_source, mode, requested_schema, action, mcp_request_id, server_name, server_url, static_client_config, traceparent, tracestate, command, args, command_name, commands, ui, actions, plan_content, recommended_action, approved, auto_approve_edits, feedback, selected_action, skills, agents, errors, warnings, servers, status, extensions) def to_dict(self) -> dict: result: dict = {} if self.already_in_use is not None: result["alreadyInUse"] = from_union([from_bool, from_none], self.already_in_use) if self.context is not None: - result["context"] = from_union([lambda x: to_class(ContextClass, x), from_str, from_none], self.context) + result["context"] = from_union([lambda x: to_class(Context, x), from_str, from_none], self.context) if self.copilot_version is not None: result["copilotVersion"] = from_union([from_str, from_none], self.copilot_version) if self.producer is not None: @@ -2848,7 +2858,7 @@ def to_dict(self) -> dict: if self.previous_mode is not None: result["previousMode"] = from_union([from_str, from_none], self.previous_mode) if self.operation is not None: - result["operation"] = from_union([lambda x: to_enum(Operation, x), from_none], self.operation) + result["operation"] = from_union([lambda x: to_enum(ChangedOperation, x), from_none], self.operation) if self.path is not None: result["path"] = from_union([from_str, from_none], self.path) if self.handoff_time is not None: @@ -2858,9 +2868,9 @@ def to_dict(self) -> dict: if self.remote_session_id is not None: result["remoteSessionId"] = from_union([from_str, from_none], self.remote_session_id) if self.repository is not None: - result["repository"] = from_union([lambda x: to_class(RepositoryClass, x), from_str, from_none], self.repository) + result["repository"] = from_union([lambda x: to_class(HandoffRepository, x), from_str, from_none], self.repository) if self.source_type is not None: - result["sourceType"] = from_union([lambda x: to_enum(SourceType, x), from_none], self.source_type) + result["sourceType"] = from_union([lambda x: to_enum(HandoffSourceType, x), from_none], self.source_type) if self.summary is not None: result["summary"] = from_union([from_str, from_none], self.summary) if self.messages_removed_during_truncation is not None: @@ -2884,7 +2894,7 @@ def to_dict(self) -> dict: if self.up_to_event_id is not None: result["upToEventId"] = from_union([from_str, from_none], self.up_to_event_id) if self.code_changes is not None: - result["codeChanges"] = from_union([lambda x: to_class(CodeChanges, x), from_none], self.code_changes) + result["codeChanges"] = from_union([lambda x: to_class(ShutdownCodeChanges, x), from_none], self.code_changes) if self.conversation_tokens is not None: result["conversationTokens"] = from_union([to_float, from_none], self.conversation_tokens) if self.current_model is not None: @@ -2894,7 +2904,7 @@ def to_dict(self) -> dict: if self.error_reason is not None: result["errorReason"] = from_union([from_str, from_none], self.error_reason) if self.model_metrics is not None: - result["modelMetrics"] = from_union([lambda x: from_dict(lambda x: to_class(ModelMetric, x), x), from_none], self.model_metrics) + result["modelMetrics"] = from_union([lambda x: from_dict(lambda x: to_class(ShutdownModelMetric, x), x), from_none], self.model_metrics) if self.session_start_time is not None: result["sessionStartTime"] = from_union([to_float, from_none], self.session_start_time) if self.shutdown_type is not None: @@ -2918,7 +2928,7 @@ def to_dict(self) -> dict: if self.head_commit is not None: result["headCommit"] = from_union([from_str, from_none], self.head_commit) if self.host_type is not None: - result["hostType"] = from_union([lambda x: to_enum(HostType, x), from_none], self.host_type) + result["hostType"] = from_union([lambda x: to_enum(ContextChangedHostType, x), from_none], self.host_type) if self.is_initial is not None: result["isInitial"] = from_union([from_bool, from_none], self.is_initial) if self.messages_length is not None: @@ -2928,9 +2938,9 @@ def to_dict(self) -> dict: if self.checkpoint_path is not None: result["checkpointPath"] = from_union([from_str, from_none], self.checkpoint_path) if self.compaction_tokens_used is not None: - result["compactionTokensUsed"] = from_union([lambda x: to_class(CompactionTokensUsed, x), from_none], self.compaction_tokens_used) + result["compactionTokensUsed"] = from_union([lambda x: to_class(CompactionCompleteCompactionTokensUsed, x), from_none], self.compaction_tokens_used) if self.error is not None: - result["error"] = from_union([lambda x: to_class(ErrorClass, x), from_str, from_none], self.error) + result["error"] = from_union([lambda x: to_class(Error, x), from_str, from_none], self.error) if self.messages_removed is not None: result["messagesRemoved"] = from_union([to_float, from_none], self.messages_removed) if self.post_compaction_tokens is not None: @@ -2948,9 +2958,9 @@ def to_dict(self) -> dict: if self.tokens_removed is not None: result["tokensRemoved"] = from_union([to_float, from_none], self.tokens_removed) if self.agent_mode is not None: - result["agentMode"] = from_union([lambda x: to_enum(AgentMode, x), from_none], self.agent_mode) + result["agentMode"] = from_union([lambda x: to_enum(UserMessageAgentMode, x), from_none], self.agent_mode) if self.attachments is not None: - result["attachments"] = from_union([lambda x: from_list(lambda x: to_class(Attachment, x), x), from_none], self.attachments) + result["attachments"] = from_union([lambda x: from_list(lambda x: to_class(UserMessageAttachment, x), x), from_none], self.attachments) if self.content is not None: result["content"] = from_union([from_str, lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) if self.interaction_id is not None: @@ -2984,7 +2994,7 @@ def to_dict(self) -> dict: if self.reasoning_text is not None: result["reasoningText"] = from_union([from_str, from_none], self.reasoning_text) if self.tool_requests is not None: - result["toolRequests"] = from_union([lambda x: from_list(lambda x: to_class(ToolRequest, x), x), from_none], self.tool_requests) + result["toolRequests"] = from_union([lambda x: from_list(lambda x: to_class(AssistantMessageToolRequest, x), x), from_none], self.tool_requests) if self.api_call_id is not None: result["apiCallId"] = from_union([from_str, from_none], self.api_call_id) if self.cache_read_tokens is not None: @@ -2992,7 +3002,7 @@ def to_dict(self) -> dict: if self.cache_write_tokens is not None: result["cacheWriteTokens"] = from_union([to_float, from_none], self.cache_write_tokens) if self.copilot_usage is not None: - result["copilotUsage"] = from_union([lambda x: to_class(CopilotUsage, x), from_none], self.copilot_usage) + result["copilotUsage"] = from_union([lambda x: to_class(AssistantUsageCopilotUsage, x), from_none], self.copilot_usage) if self.cost is not None: result["cost"] = from_union([to_float, from_none], self.cost) if self.duration is not None: @@ -3006,7 +3016,9 @@ def to_dict(self) -> dict: if self.model is not None: result["model"] = from_union([from_str, from_none], self.model) if self.quota_snapshots is not None: - result["quotaSnapshots"] = from_union([lambda x: from_dict(lambda x: to_class(QuotaSnapshot, x), x), from_none], self.quota_snapshots) + result["quotaSnapshots"] = from_union([lambda x: from_dict(lambda x: to_class(AssistantUsageQuotaSnapshot, x), x), from_none], self.quota_snapshots) + if self.reasoning_tokens is not None: + result["reasoningTokens"] = from_union([to_float, from_none], self.reasoning_tokens) if self.ttft_ms is not None: result["ttftMs"] = from_union([to_float, from_none], self.ttft_ms) if self.reason is not None: @@ -3064,11 +3076,11 @@ def to_dict(self) -> dict: if self.output is not None: result["output"] = self.output if self.metadata is not None: - result["metadata"] = from_union([lambda x: to_class(Metadata, x), from_none], self.metadata) + result["metadata"] = from_union([lambda x: to_class(SystemMessageMetadata, x), from_none], self.metadata) if self.role is not None: - result["role"] = from_union([lambda x: to_enum(Role, x), from_none], self.role) + result["role"] = from_union([lambda x: to_enum(SystemMessageRole, x), from_none], self.role) if self.kind is not None: - result["kind"] = from_union([lambda x: to_class(KindClass, x), from_none], self.kind) + result["kind"] = from_union([lambda x: to_class(SystemNotification, 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: @@ -3086,11 +3098,11 @@ def to_dict(self) -> dict: if self.elicitation_source is not None: result["elicitationSource"] = from_union([from_str, from_none], self.elicitation_source) if self.mode is not None: - result["mode"] = from_union([lambda x: to_enum(Mode, x), from_none], self.mode) + result["mode"] = from_union([lambda x: to_enum(ElicitationRequestedMode, x), from_none], self.mode) if self.requested_schema is not None: - result["requestedSchema"] = from_union([lambda x: to_class(RequestedSchema, x), from_none], self.requested_schema) + result["requestedSchema"] = from_union([lambda x: to_class(ElicitationRequestedSchema, x), from_none], self.requested_schema) if self.action is not None: - result["action"] = from_union([lambda x: to_enum(DataAction, x), from_none], self.action) + result["action"] = from_union([lambda x: to_enum(ElicitationCompletedAction, x), from_none], self.action) if self.mcp_request_id is not None: result["mcpRequestId"] = from_union([to_float, from_str, from_none], self.mcp_request_id) if self.server_name is not None: @@ -3098,7 +3110,7 @@ def to_dict(self) -> dict: if self.server_url is not None: result["serverUrl"] = from_union([from_str, from_none], self.server_url) if self.static_client_config is not None: - result["staticClientConfig"] = from_union([lambda x: to_class(StaticClientConfig, x), from_none], self.static_client_config) + result["staticClientConfig"] = from_union([lambda x: to_class(MCPOauthRequiredStaticClientConfig, x), from_none], self.static_client_config) if self.traceparent is not None: result["traceparent"] = from_union([from_str, from_none], self.traceparent) if self.tracestate is not None: @@ -3110,9 +3122,9 @@ def to_dict(self) -> dict: if self.command_name is not None: result["commandName"] = from_union([from_str, from_none], self.command_name) if self.commands is not None: - result["commands"] = from_union([lambda x: from_list(lambda x: to_class(DataCommand, x), x), from_none], self.commands) + result["commands"] = from_union([lambda x: from_list(lambda x: to_class(CommandsChangedCommand, x), x), from_none], self.commands) if self.ui is not None: - result["ui"] = from_union([lambda x: to_class(UI, x), from_none], self.ui) + result["ui"] = from_union([lambda x: to_class(CapabilitiesChangedUI, x), from_none], self.ui) if self.actions is not None: result["actions"] = from_union([lambda x: from_list(from_str, x), from_none], self.actions) if self.plan_content is not None: @@ -3128,19 +3140,19 @@ def to_dict(self) -> dict: if self.selected_action is not None: result["selectedAction"] = from_union([from_str, from_none], self.selected_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) + result["skills"] = from_union([lambda x: from_list(lambda x: to_class(SkillsLoadedSkill, x), x), from_none], self.skills) if self.agents is not None: - result["agents"] = from_union([lambda x: from_list(lambda x: to_class(Agent, x), x), from_none], self.agents) + result["agents"] = from_union([lambda x: from_list(lambda x: to_class(CustomAgentsUpdatedAgent, 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) + result["servers"] = from_union([lambda x: from_list(lambda x: to_class(MCPServersLoadedServer, x), x), from_none], self.servers) if self.status is not None: - result["status"] = from_union([lambda x: to_enum(ServerStatus, x), from_none], self.status) + result["status"] = from_union([lambda x: to_enum(MCPServerStatus, x), from_none], self.status) if self.extensions is not None: - result["extensions"] = from_union([lambda x: from_list(lambda x: to_class(Extension, x), x), from_none], self.extensions) + result["extensions"] = from_union([lambda x: from_list(lambda x: to_class(ExtensionsLoadedExtension, x), x), from_none], self.extensions) return result diff --git a/python/copilot/session.py b/python/copilot/session.py index 45e8826b7..4c6dd0fa1 100644 --- a/python/copilot/session.py +++ b/python/copilot/session.py @@ -22,30 +22,28 @@ from ._jsonrpc import JsonRpcError, ProcessExitedError from ._telemetry import get_trace_context, trace_context from .generated.rpc import ( - Action, ClientSessionApiHandlers, + CommandsHandlePendingCommandRequest, + HandlePendingElicitationRequest, Kind, - Level, - Property, - PropertyType, - RequestedSchema, + LogRequest, + ModelSwitchToRequest, + PermissionDecision, + PermissionDecisionRequest, RequestedSchemaType, - ResultResult, - SessionCommandsHandlePendingCommandParams, SessionFsHandler, - SessionLogParams, - SessionModelSwitchToParams, - SessionPermissionsHandlePendingPermissionRequestParams, - SessionPermissionsHandlePendingPermissionRequestParamsResult, + SessionLogLevel, SessionRpc, - SessionToolsHandlePendingToolCallParams, - SessionUIElicitationParams, - SessionUIHandlePendingElicitationParams, - SessionUIHandlePendingElicitationParamsResult, -) -from .generated.rpc import ( - ModelCapabilitiesOverride as _RpcModelCapabilitiesOverride, + ToolCallResult, + ToolsHandlePendingToolCallRequest, + UIElicitationAction, + UIElicitationRequest, + UIElicitationResponse, + UIElicitationSchema, + UIElicitationSchemaProperty, + UIElicitationSchemaPropertyNumberType, ) +from .generated.rpc import ModelCapabilitiesOverride as _RpcModelCapabilitiesOverride from .generated.session_events import ( PermissionRequest, SessionEvent, @@ -439,12 +437,12 @@ async def elicitation(self, params: ElicitationParams) -> ElicitationResult: """ self._session._assert_elicitation() rpc_result = await self._session.rpc.ui.elicitation( - SessionUIElicitationParams( + UIElicitationRequest( message=params["message"], - requested_schema=RequestedSchema.from_dict(params["requestedSchema"]), + requested_schema=UIElicitationSchema.from_dict(params["requestedSchema"]), ) ) - result: ElicitationResult = {"action": rpc_result.action.value} # type: ignore[typeddict-item] + result: ElicitationResult = {"action": rpc_result.action.value} if rpc_result.content is not None: result["content"] = rpc_result.content return result @@ -463,19 +461,22 @@ async def confirm(self, message: str) -> bool: """ self._session._assert_elicitation() rpc_result = await self._session.rpc.ui.elicitation( - SessionUIElicitationParams( + UIElicitationRequest( message=message, - requested_schema=RequestedSchema( + requested_schema=UIElicitationSchema( type=RequestedSchemaType.OBJECT, properties={ - "confirmed": Property(type=PropertyType.BOOLEAN, default=True), + "confirmed": UIElicitationSchemaProperty( + type=UIElicitationSchemaPropertyNumberType.BOOLEAN, + default=True, + ), }, required=["confirmed"], ), ) ) return ( - rpc_result.action == Action.ACCEPT + rpc_result.action == UIElicitationAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("confirmed") is True ) @@ -495,19 +496,22 @@ async def select(self, message: str, options: list[str]) -> str | None: """ self._session._assert_elicitation() rpc_result = await self._session.rpc.ui.elicitation( - SessionUIElicitationParams( + UIElicitationRequest( message=message, - requested_schema=RequestedSchema( + requested_schema=UIElicitationSchema( type=RequestedSchemaType.OBJECT, properties={ - "selection": Property(type=PropertyType.STRING, enum=options), + "selection": UIElicitationSchemaProperty( + type=UIElicitationSchemaPropertyNumberType.STRING, + enum=options, + ), }, required=["selection"], ), ) ) if ( - rpc_result.action == Action.ACCEPT + rpc_result.action == UIElicitationAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("selection") is not None ): @@ -535,9 +539,9 @@ async def input(self, message: str, options: InputOptions | None = None) -> str field[key] = options[key] rpc_result = await self._session.rpc.ui.elicitation( - SessionUIElicitationParams( + UIElicitationRequest( message=message, - requested_schema=RequestedSchema.from_dict( + requested_schema=UIElicitationSchema.from_dict( { "type": "object", "properties": {"value": field}, @@ -547,7 +551,7 @@ async def input(self, message: str, options: InputOptions | None = None) -> str ) ) if ( - rpc_result.action == Action.ACCEPT + rpc_result.action == UIElicitationAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("value") is not None ): @@ -1345,19 +1349,19 @@ async def _execute_tool_and_respond( # failures send the full structured result to preserve metadata. if tool_result._from_exception: await self.rpc.tools.handle_pending_tool_call( - SessionToolsHandlePendingToolCallParams( + ToolsHandlePendingToolCallRequest( request_id=request_id, error=tool_result.error, ) ) else: await self.rpc.tools.handle_pending_tool_call( - SessionToolsHandlePendingToolCallParams( + ToolsHandlePendingToolCallRequest( request_id=request_id, - result=ResultResult( + result=ToolCallResult( text_result_for_llm=tool_result.text_result_for_llm, - result_type=tool_result.result_type, error=tool_result.error, + result_type=tool_result.result_type, tool_telemetry=tool_result.tool_telemetry, ), ) @@ -1365,7 +1369,7 @@ async def _execute_tool_and_respond( except Exception as exc: try: await self.rpc.tools.handle_pending_tool_call( - SessionToolsHandlePendingToolCallParams( + ToolsHandlePendingToolCallRequest( request_id=request_id, error=str(exc), ) @@ -1389,7 +1393,7 @@ async def _execute_permission_and_respond( if result.kind == "no-result": return - perm_result = SessionPermissionsHandlePendingPermissionRequestParamsResult( + perm_result = PermissionDecision( kind=Kind(result.kind), rules=result.rules, feedback=result.feedback, @@ -1398,7 +1402,7 @@ async def _execute_permission_and_respond( ) await self.rpc.permissions.handle_pending_permission_request( - SessionPermissionsHandlePendingPermissionRequestParams( + PermissionDecisionRequest( request_id=request_id, result=perm_result, ) @@ -1406,9 +1410,9 @@ async def _execute_permission_and_respond( except Exception: try: await self.rpc.permissions.handle_pending_permission_request( - SessionPermissionsHandlePendingPermissionRequestParams( + PermissionDecisionRequest( request_id=request_id, - result=SessionPermissionsHandlePendingPermissionRequestParamsResult( + result=PermissionDecision( kind=Kind.DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER, ), ) @@ -1430,7 +1434,7 @@ async def _execute_command_and_respond( if not handler: try: await self.rpc.commands.handle_pending_command( - SessionCommandsHandlePendingCommandParams( + CommandsHandlePendingCommandRequest( request_id=request_id, error=f"Unknown command: {command_name}", ) @@ -1450,13 +1454,13 @@ async def _execute_command_and_respond( if inspect.isawaitable(result): await result await self.rpc.commands.handle_pending_command( - SessionCommandsHandlePendingCommandParams(request_id=request_id) + CommandsHandlePendingCommandRequest(request_id=request_id) ) except Exception as exc: message = str(exc) try: await self.rpc.commands.handle_pending_command( - SessionCommandsHandlePendingCommandParams( + CommandsHandlePendingCommandRequest( request_id=request_id, error=message, ) @@ -1484,12 +1488,12 @@ async def _handle_elicitation_request( result = await result result = cast(ElicitationResult, result) action_val = result.get("action", "cancel") - rpc_result = SessionUIHandlePendingElicitationParamsResult( - action=Action(action_val), + rpc_result = UIElicitationResponse( + action=UIElicitationAction(action_val), content=result.get("content"), ) await self.rpc.ui.handle_pending_elicitation( - SessionUIHandlePendingElicitationParams( + HandlePendingElicitationRequest( request_id=request_id, result=rpc_result, ) @@ -1498,10 +1502,10 @@ async def _handle_elicitation_request( # Handler failed — attempt to cancel so the request doesn't hang try: await self.rpc.ui.handle_pending_elicitation( - SessionUIHandlePendingElicitationParams( + HandlePendingElicitationRequest( request_id=request_id, - result=SessionUIHandlePendingElicitationParamsResult( - action=Action.CANCEL, + result=UIElicitationResponse( + action=UIElicitationAction.CANCEL, ), ) ) @@ -1939,7 +1943,7 @@ async def set_model( _capabilities_to_dict(model_capabilities) ) await self.rpc.model.switch_to( - SessionModelSwitchToParams( + ModelSwitchToRequest( model_id=model, reasoning_effort=reasoning_effort, model_capabilities=rpc_caps, @@ -1973,9 +1977,9 @@ async def log( >>> await session.log("Operation failed", level="error") >>> await session.log("Temporary status update", ephemeral=True) """ - params = SessionLogParams( + params = LogRequest( message=message, - level=Level(level) if level is not None else None, + level=SessionLogLevel(level) if level is not None else None, ephemeral=ephemeral, ) await self.rpc.log(params) diff --git a/python/e2e/test_agent_and_compact_rpc.py b/python/e2e/test_agent_and_compact_rpc.py index 047765641..1d1842fd0 100644 --- a/python/e2e/test_agent_and_compact_rpc.py +++ b/python/e2e/test_agent_and_compact_rpc.py @@ -4,7 +4,7 @@ from copilot import CopilotClient from copilot.client import SubprocessConfig -from copilot.generated.rpc import SessionAgentSelectParams +from copilot.generated.rpc import AgentSelectRequest from copilot.session import PermissionHandler from .testharness import CLI_PATH, E2ETestContext @@ -98,9 +98,7 @@ async def test_should_select_and_get_current_agent(self): ) # Select the agent - select_result = await session.rpc.agent.select( - SessionAgentSelectParams(name="test-agent") - ) + select_result = await session.rpc.agent.select(AgentSelectRequest(name="test-agent")) assert select_result.agent is not None assert select_result.agent.name == "test-agent" assert select_result.agent.display_name == "Test Agent" @@ -135,7 +133,7 @@ async def test_should_deselect_current_agent(self): ) # Select then deselect - await session.rpc.agent.select(SessionAgentSelectParams(name="test-agent")) + await session.rpc.agent.select(AgentSelectRequest(name="test-agent")) await session.rpc.agent.deselect() # Verify no agent is selected diff --git a/python/e2e/test_rpc.py b/python/e2e/test_rpc.py index a86f874db..a7c5ff321 100644 --- a/python/e2e/test_rpc.py +++ b/python/e2e/test_rpc.py @@ -4,7 +4,7 @@ from copilot import CopilotClient from copilot.client import SubprocessConfig -from copilot.generated.rpc import PingParams +from copilot.generated.rpc import PingRequest from copilot.session import PermissionHandler from .testharness import CLI_PATH, E2ETestContext @@ -21,7 +21,7 @@ async def test_should_call_rpc_ping_with_typed_params(self): try: await client.start() - result = await client.rpc.ping(PingParams(message="typed rpc test")) + result = await client.rpc.ping(PingRequest(message="typed rpc test")) assert result.message == "pong: typed rpc test" assert isinstance(result.timestamp, (int, float)) @@ -91,7 +91,7 @@ async def test_should_call_session_rpc_model_get_current(self, ctx: E2ETestConte @pytest.mark.skip(reason="session.model.switchTo not yet implemented in CLI") async def test_should_call_session_rpc_model_switch_to(self, ctx: E2ETestContext): """Test calling session.rpc.model.switchTo""" - from copilot.generated.rpc import SessionModelSwitchToParams + from copilot.generated.rpc import ModelSwitchToRequest session = await ctx.client.create_session( on_permission_request=PermissionHandler.approve_all, model="claude-sonnet-4.5" @@ -103,7 +103,7 @@ async def test_should_call_session_rpc_model_switch_to(self, ctx: E2ETestContext # Switch to a different model with reasoning effort result = await session.rpc.model.switch_to( - SessionModelSwitchToParams(model_id="gpt-4.1", reasoning_effort="high") + ModelSwitchToRequest(model_id="gpt-4.1", reasoning_effort="high") ) assert result.model_id == "gpt-4.1" @@ -114,7 +114,7 @@ async def test_should_call_session_rpc_model_switch_to(self, ctx: E2ETestContext @pytest.mark.asyncio async def test_get_and_set_session_mode(self): """Test getting and setting session mode""" - from copilot.generated.rpc import Mode, SessionModeSetParams + from copilot.generated.rpc import ModeSetRequest, SessionMode client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH, use_stdio=True)) @@ -126,21 +126,21 @@ async def test_get_and_set_session_mode(self): # Get initial mode (default should be interactive) initial = await session.rpc.mode.get() - assert initial.mode == Mode.INTERACTIVE + assert initial == SessionMode.INTERACTIVE # Switch to plan mode - plan_result = await session.rpc.mode.set(SessionModeSetParams(mode=Mode.PLAN)) - assert plan_result.mode == Mode.PLAN + plan_result = await session.rpc.mode.set(ModeSetRequest(mode=SessionMode.PLAN)) + assert plan_result == SessionMode.PLAN # Verify mode persisted after_plan = await session.rpc.mode.get() - assert after_plan.mode == Mode.PLAN + assert after_plan == SessionMode.PLAN # Switch back to interactive interactive_result = await session.rpc.mode.set( - SessionModeSetParams(mode=Mode.INTERACTIVE) + ModeSetRequest(mode=SessionMode.INTERACTIVE) ) - assert interactive_result.mode == Mode.INTERACTIVE + assert interactive_result == SessionMode.INTERACTIVE await session.disconnect() await client.stop() @@ -150,7 +150,7 @@ async def test_get_and_set_session_mode(self): @pytest.mark.asyncio async def test_read_update_and_delete_plan(self): """Test reading, updating, and deleting plan""" - from copilot.generated.rpc import SessionPlanUpdateParams + from copilot.generated.rpc import PlanUpdateRequest client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH, use_stdio=True)) @@ -167,7 +167,7 @@ async def test_read_update_and_delete_plan(self): # Create/update plan plan_content = "# Test Plan\n\n- Step 1\n- Step 2" - await session.rpc.plan.update(SessionPlanUpdateParams(content=plan_content)) + await session.rpc.plan.update(PlanUpdateRequest(content=plan_content)) # Verify plan exists and has correct content after_update = await session.rpc.plan.read() @@ -191,8 +191,8 @@ async def test_read_update_and_delete_plan(self): async def test_create_list_and_read_workspace_files(self): """Test creating, listing, and reading workspace files""" from copilot.generated.rpc import ( - SessionWorkspaceCreateFileParams, - SessionWorkspaceReadFileParams, + WorkspaceCreateFileRequest, + WorkspaceReadFileRequest, ) client = CopilotClient(SubprocessConfig(cli_path=CLI_PATH, use_stdio=True)) @@ -210,7 +210,7 @@ async def test_create_list_and_read_workspace_files(self): # Create a file file_content = "Hello, workspace!" await session.rpc.workspace.create_file( - SessionWorkspaceCreateFileParams(content=file_content, path="test.txt") + WorkspaceCreateFileRequest(content=file_content, path="test.txt") ) # List files @@ -219,13 +219,13 @@ async def test_create_list_and_read_workspace_files(self): # Read file read_result = await session.rpc.workspace.read_file( - SessionWorkspaceReadFileParams(path="test.txt") + WorkspaceReadFileRequest(path="test.txt") ) assert read_result.content == file_content # Create nested file await session.rpc.workspace.create_file( - SessionWorkspaceCreateFileParams(content="Nested content", path="subdir/nested.txt") + WorkspaceCreateFileRequest(content="Nested content", path="subdir/nested.txt") ) after_nested = await session.rpc.workspace.list_files() diff --git a/python/test_commands_and_elicitation.py b/python/test_commands_and_elicitation.py index 9ee710fe0..6b8518e26 100644 --- a/python/test_commands_and_elicitation.py +++ b/python/test_commands_and_elicitation.py @@ -579,7 +579,7 @@ async def mock_request(method, params): from copilot.generated.session_events import ( Data, - RequestedSchema, + ElicitationRequestedSchema, RequestedSchemaType, SessionEvent, SessionEventType, @@ -589,7 +589,7 @@ async def mock_request(method, params): data=Data( request_id="req-schema-1", message="Fill in your details", - requested_schema=RequestedSchema( + requested_schema=ElicitationRequestedSchema( type=RequestedSchemaType.OBJECT, properties={ "name": {"type": "string"}, @@ -638,14 +638,14 @@ async def test_capabilities_changed_event_updates_session(self): session._set_capabilities({}) from copilot.generated.session_events import ( - UI, + CapabilitiesChangedUI, Data, SessionEvent, SessionEventType, ) event = SessionEvent( - data=Data(ui=UI(elicitation=True)), + data=Data(ui=CapabilitiesChangedUI(elicitation=True)), id="evt-cap-1", timestamp="2025-01-01T00:00:00Z", type=SessionEventType.CAPABILITIES_CHANGED, diff --git a/python/test_rpc_timeout.py b/python/test_rpc_timeout.py index 7fca7615b..b6f07caed 100644 --- a/python/test_rpc_timeout.py +++ b/python/test_rpc_timeout.py @@ -6,14 +6,14 @@ from copilot.generated.rpc import ( FleetApi, - Mode, + FleetStartRequest, ModeApi, + ModeSetRequest, PlanApi, ServerModelsApi, ServerToolsApi, - SessionFleetStartParams, - SessionModeSetParams, - ToolsListParams, + SessionMode, + ToolsListRequest, ) @@ -33,7 +33,7 @@ async def test_default_timeout_not_forwarded(self): client.request = AsyncMock(return_value={"started": True}) api = FleetApi(client, "sess-1") - await api.start(SessionFleetStartParams(prompt="go")) + await api.start(FleetStartRequest(prompt="go")) client.request.assert_called_once() _, kwargs = client.request.call_args @@ -45,7 +45,7 @@ async def test_custom_timeout_forwarded(self): client.request = AsyncMock(return_value={"started": True}) api = FleetApi(client, "sess-1") - await api.start(SessionFleetStartParams(prompt="go"), timeout=600.0) + await api.start(FleetStartRequest(prompt="go"), timeout=600.0) _, kwargs = client.request.call_args assert kwargs["timeout"] == 600.0 @@ -56,7 +56,7 @@ async def test_timeout_on_session_params_method(self): client.request = AsyncMock(return_value={"mode": "plan"}) api = ModeApi(client, "sess-1") - await api.set(SessionModeSetParams(mode=Mode.PLAN), timeout=120.0) + await api.set(ModeSetRequest(mode=SessionMode.PLAN), timeout=120.0) _, kwargs = client.request.call_args assert kwargs["timeout"] == 120.0 @@ -93,7 +93,7 @@ async def test_timeout_on_server_params_method(self): client.request = AsyncMock(return_value={"tools": []}) api = ServerToolsApi(client) - await api.list(ToolsListParams(), timeout=60.0) + await api.list(ToolsListRequest(), timeout=60.0) _, kwargs = client.request.call_args assert kwargs["timeout"] == 60.0 @@ -104,7 +104,7 @@ async def test_default_timeout_on_server_params_method(self): client.request = AsyncMock(return_value={"tools": []}) api = ServerToolsApi(client) - await api.list(ToolsListParams()) + await api.list(ToolsListRequest()) _, kwargs = client.request.call_args assert "timeout" not in kwargs diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index e6042eae5..2cf01d499 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -12,13 +12,15 @@ import path from "path"; import { promisify } from "util"; import type { JSONSchema7 } from "json-schema"; import { - getSessionEventsSchemaPath, + cloneSchemaForCodegen, getApiSchemaPath, - writeGeneratedFile, - isRpcMethod, + getRpcSchemaTypeName, + getSessionEventsSchemaPath, isNodeFullyExperimental, - EXCLUDED_EVENT_TYPES, + isObjectSchema, + isRpcMethod, REPO_ROOT, + writeGeneratedFile, type ApiSchema, type RpcMethod, } from "./utils.js"; @@ -297,12 +299,12 @@ interface EventVariant { let generatedEnums = new Map(); -function getOrCreateEnum(parentClassName: string, propName: string, values: string[], enumOutput: string[], description?: string): string { +function getOrCreateEnum(parentClassName: string, propName: string, values: string[], enumOutput: string[], description?: string, explicitName?: string): string { const valuesKey = [...values].sort().join("|"); for (const [, existing] of generatedEnums) { if ([...existing.values].sort().join("|") === valuesKey) return existing.enumName; } - const enumName = `${parentClassName}${propName}`; + const enumName = explicitName ?? `${parentClassName}${propName}`; generatedEnums.set(enumName, { enumName, values }); const lines: string[] = []; @@ -336,8 +338,7 @@ function extractEventVariants(schema: JSONSchema7): EventVariant[] { dataSchema, dataDescription: dataSchema?.description, }; - }) - .filter((v) => !EXCLUDED_EVENT_TYPES.has(v.typeName)); + }); } /** @@ -515,7 +516,7 @@ function resolveSessionPropertyType( const variants = nonNull as JSONSchema7[]; const discriminatorInfo = findDiscriminator(variants); if (discriminatorInfo) { - const baseClassName = `${parentClassName}${propName}`; + const baseClassName = (propSchema.title as string) ?? `${parentClassName}${propName}`; const renamedBase = applyTypeRename(baseClassName); const polymorphicCode = generatePolymorphicClasses(baseClassName, discriminatorInfo.property, variants, knownTypes, nestedClasses, enumOutput, propSchema.description); nestedClasses.set(renamedBase, polymorphicCode); @@ -525,11 +526,11 @@ function resolveSessionPropertyType( return hasNull || !isRequired ? "object?" : "object"; } if (propSchema.enum && Array.isArray(propSchema.enum)) { - const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description); + const enumName = getOrCreateEnum(parentClassName, propName, propSchema.enum as string[], enumOutput, propSchema.description, propSchema.title as string | undefined); return isRequired ? enumName : `${enumName}?`; } if (propSchema.type === "object" && propSchema.properties) { - const nestedClassName = `${parentClassName}${propName}`; + const nestedClassName = (propSchema.title as string) ?? `${parentClassName}${propName}`; nestedClasses.set(nestedClassName, generateNestedClass(nestedClassName, propSchema, knownTypes, nestedClasses, enumOutput)); return isRequired ? nestedClassName : `${nestedClassName}?`; } @@ -540,7 +541,7 @@ function resolveSessionPropertyType( const variants = items.anyOf.filter((v): v is JSONSchema7 => typeof v === "object"); const discriminatorInfo = findDiscriminator(variants); if (discriminatorInfo) { - const baseClassName = `${parentClassName}${propName}Item`; + const baseClassName = (items.title as string) ?? `${parentClassName}${propName}Item`; const renamedBase = applyTypeRename(baseClassName); const polymorphicCode = generatePolymorphicClasses(baseClassName, discriminatorInfo.property, variants, knownTypes, nestedClasses, enumOutput, items.description); nestedClasses.set(renamedBase, polymorphicCode); @@ -548,12 +549,12 @@ function resolveSessionPropertyType( } } if (items.type === "object" && items.properties) { - const itemClassName = `${parentClassName}${propName}Item`; + const itemClassName = (items.title as string) ?? `${parentClassName}${propName}Item`; nestedClasses.set(itemClassName, generateNestedClass(itemClassName, items, knownTypes, nestedClasses, enumOutput)); return isRequired ? `${itemClassName}[]` : `${itemClassName}[]?`; } if (items.enum && Array.isArray(items.enum)) { - const enumName = getOrCreateEnum(parentClassName, `${propName}Item`, items.enum as string[], enumOutput, items.description); + const enumName = getOrCreateEnum(parentClassName, `${propName}Item`, items.enum as string[], enumOutput, items.description, items.title as string | undefined); return isRequired ? `${enumName}[]` : `${enumName}[]?`; } const itemType = schemaTypeToCSharp(items, true, knownTypes); @@ -690,7 +691,7 @@ namespace GitHub.Copilot.SDK; export async function generateSessionEvents(schemaPath?: string): Promise { console.log("C#: generating session-events..."); const resolvedPath = schemaPath ?? (await getSessionEventsSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7); const code = generateSessionEventsCode(schema); const outPath = await writeGeneratedFile("dotnet/src/Generated/SessionEvents.cs", code); console.log(` ✓ ${outPath}`); @@ -702,6 +703,7 @@ export async function generateSessionEvents(schemaPath?: string): Promise // ══════════════════════════════════════════════════════════════════════════════ let emittedRpcClassSchemas = new Map(); +let emittedRpcEnumResultTypes = new Set(); let experimentalRpcTypes = new Set(); let rpcKnownTypes = new Map(); let rpcEnumOutput: string[] = []; @@ -714,12 +716,12 @@ function singularPascal(s: string): string { return p; } -function resultTypeName(rpcMethod: string): string { - return `${typeToClassName(rpcMethod)}Result`; +function resultTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.result, `${typeToClassName(method.rpcMethod)}Result`); } -function paramsTypeName(rpcMethod: string): string { - return `${typeToClassName(rpcMethod)}Params`; +function paramsTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.params, `${typeToClassName(method.rpcMethod)}Request`); } function stableStringify(value: unknown): string { @@ -744,7 +746,14 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam } // Handle enums (string unions like "interactive" | "plan" | "autopilot") if (schema.enum && Array.isArray(schema.enum)) { - const enumName = getOrCreateEnum(parentClassName, propName, schema.enum as string[], rpcEnumOutput, schema.description); + const enumName = getOrCreateEnum( + parentClassName, + propName, + schema.enum as string[], + rpcEnumOutput, + schema.description, + schema.title as string | undefined, + ); return isRequired ? enumName : `${enumName}?`; } if (schema.type === "object" && schema.properties) { @@ -757,7 +766,18 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam if (items.type === "object" && items.properties) { const itemClass = (items.title as string) ?? singularPascal(propName); classes.push(emitRpcClass(itemClass, items, "public", classes)); - return isRequired ? `IList<${itemClass}>` : `IList<${itemClass}>?`; + return isRequired ? `List<${itemClass}>` : `List<${itemClass}>?`; + } + if (items.enum && Array.isArray(items.enum)) { + const itemEnum = getOrCreateEnum( + parentClassName, + `${propName}Item`, + items.enum as string[], + rpcEnumOutput, + items.description, + items.title as string | undefined, + ); + return isRequired ? `List<${itemEnum}>` : `List<${itemEnum}>?`; } const itemType = schemaTypeToCSharp(items, true, rpcKnownTypes); return isRequired ? `IList<${itemType}>` : `IList<${itemType}>?`; @@ -765,7 +785,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam if (schema.type === "object" && schema.additionalProperties && typeof schema.additionalProperties === "object") { const vs = schema.additionalProperties as JSONSchema7; if (vs.type === "object" && vs.properties) { - const valClass = `${parentClassName}${propName}Value`; + const valClass = (vs.title as string) ?? `${parentClassName}${propName}Value`; classes.push(emitRpcClass(valClass, vs, "public", classes)); return isRequired ? `IDictionary` : `IDictionary?`; } @@ -832,6 +852,21 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi return lines.join("\n"); } +/** + * Emit the type for a non-object RPC result schema (e.g., a bare enum). + * Returns the C# type name to use in method signatures. For enums, ensures the enum + * is created via getOrCreateEnum. For other primitives, returns the mapped C# type. + */ +function emitNonObjectResultType(typeName: string, schema: JSONSchema7, classes: string[]): string { + if (schema.enum && Array.isArray(schema.enum)) { + const enumName = getOrCreateEnum("", typeName, schema.enum as string[], rpcEnumOutput, schema.description, typeName); + emittedRpcEnumResultTypes.add(enumName); + return enumName; + } + // For other non-object types, use the basic type mapping + return schemaTypeToCSharp(schema, true, rpcKnownTypes); +} + /** * Emit ServerRpc as an instance class (like SessionRpc but without sessionId). */ @@ -917,19 +952,23 @@ function emitServerInstanceMethod( groupExperimental: boolean ): void { const methodName = toPascalCase(name); - const resultClassName = `${typeToClassName(method.rpcMethod)}Result`; + let resultClassName = resultTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } - const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); - if (resultClass) classes.push(resultClass); + if (isObjectSchema(method.result)) { + const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); + if (resultClass) classes.push(resultClass); + } else if (method.result) { + resultClassName = emitNonObjectResultType(resultClassName, method.result, classes); + } const paramEntries = method.params?.properties ? Object.entries(method.params.properties) : []; const requiredSet = new Set(method.params?.required || []); let requestClassName: string | null = null; if (paramEntries.length > 0) { - requestClassName = `${typeToClassName(method.rpcMethod)}Request`; + requestClassName = paramsTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(requestClassName); } @@ -1004,12 +1043,16 @@ function emitSessionRpcClasses(node: Record, classes: string[]) function emitSessionMethod(key: string, method: RpcMethod, lines: string[], classes: string[], indent: string, groupExperimental: boolean): void { const methodName = toPascalCase(key); - const resultClassName = `${typeToClassName(method.rpcMethod)}Result`; + let resultClassName = resultTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } - const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); - if (resultClass) classes.push(resultClass); + if (isObjectSchema(method.result)) { + const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); + if (resultClass) classes.push(resultClass); + } else if (method.result) { + resultClassName = emitNonObjectResultType(resultClassName, method.result, classes); + } const paramEntries = (method.params?.properties ? Object.entries(method.params.properties) : []).filter(([k]) => k !== "sessionId"); const requiredSet = new Set(method.params?.required || []); @@ -1021,7 +1064,7 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas return aReq - bReq; }); - const requestClassName = `${typeToClassName(method.rpcMethod)}Request`; + const requestClassName = paramsTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(requestClassName); } @@ -1096,12 +1139,16 @@ function emitClientSessionApiRegistration(clientSchema: Record, for (const { methods } of groups) { for (const method of methods) { if (method.result) { - const resultClass = emitRpcClass(resultTypeName(method.rpcMethod), method.result, "public", classes); - if (resultClass) classes.push(resultClass); + if (isObjectSchema(method.result)) { + const resultClass = emitRpcClass(resultTypeName(method), method.result, "public", classes); + if (resultClass) classes.push(resultClass); + } else { + emitNonObjectResultType(resultTypeName(method), method.result, classes); + } } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { - const paramsClass = emitRpcClass(paramsTypeName(method.rpcMethod), method.params, "public", classes); + const paramsClass = emitRpcClass(paramsTypeName(method), method.params, "public", classes); if (paramsClass) classes.push(paramsClass); } } @@ -1118,13 +1165,13 @@ function emitClientSessionApiRegistration(clientSchema: Record, lines.push(`{`); for (const method of methods) { const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; - const taskType = method.result ? `Task<${resultTypeName(method.rpcMethod)}>` : "Task"; + const taskType = method.result ? `Task<${resultTypeName(method)}>` : "Task"; lines.push(` /// Handles "${method.rpcMethod}".`); if (method.stability === "experimental" && !groupExperimental) { lines.push(` [Experimental(Diagnostics.Experimental)]`); } if (hasParams) { - lines.push(` ${taskType} ${clientHandlerMethodName(method.rpcMethod)}(${paramsTypeName(method.rpcMethod)} request, CancellationToken cancellationToken = default);`); + lines.push(` ${taskType} ${clientHandlerMethodName(method.rpcMethod)}(${paramsTypeName(method)} request, CancellationToken cancellationToken = default);`); } else { lines.push(` ${taskType} ${clientHandlerMethodName(method.rpcMethod)}(CancellationToken cancellationToken = default);`); } @@ -1160,8 +1207,8 @@ function emitClientSessionApiRegistration(clientSchema: Record, const handlerProperty = toPascalCase(groupName); const handlerMethod = clientHandlerMethodName(method.rpcMethod); const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; - const paramsClass = paramsTypeName(method.rpcMethod); - const taskType = method.result ? `Task<${resultTypeName(method.rpcMethod)}>` : "Task"; + const paramsClass = paramsTypeName(method); + const taskType = method.result ? `Task<${resultTypeName(method)}>` : "Task"; const registrationVar = `register${typeToClassName(method.rpcMethod)}Method`; if (hasParams) { @@ -1193,6 +1240,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, function generateRpcCode(schema: ApiSchema): string { emittedRpcClassSchemas.clear(); + emittedRpcEnumResultTypes.clear(); experimentalRpcTypes.clear(); rpcKnownTypes.clear(); rpcEnumOutput = []; @@ -1237,7 +1285,7 @@ internal static class Diagnostics if (clientSessionParts.length > 0) lines.push(...clientSessionParts, ""); // Add JsonSerializerContext for AOT/trimming support - const typeNames = [...emittedRpcClassSchemas.keys()].sort(); + const typeNames = [...emittedRpcClassSchemas.keys(), ...emittedRpcEnumResultTypes].sort(); if (typeNames.length > 0) { lines.push(`[JsonSourceGenerationOptions(`); lines.push(` JsonSerializerDefaults.Web,`); @@ -1253,7 +1301,7 @@ internal static class Diagnostics export async function generateRpc(schemaPath?: string): Promise { console.log("C#: generating RPC types..."); const resolvedPath = schemaPath ?? (await getApiSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema); const code = generateRpcCode(schema); const outPath = await writeGeneratedFile("dotnet/src/Generated/Rpc.cs", code); console.log(` ✓ ${outPath}`); diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 101702f18..70a137bfb 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -12,9 +12,11 @@ import type { JSONSchema7 } from "json-schema"; import { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } from "quicktype-core"; import { promisify } from "util"; import { - EXCLUDED_EVENT_TYPES, + cloneSchemaForCodegen, getApiSchemaPath, + getRpcSchemaTypeName, getSessionEventsSchemaPath, + hoistTitledSchemas, isNodeFullyExperimental, isRpcMethod, postProcessSchema, @@ -96,6 +98,59 @@ function postProcessEnumConstants(code: string): string { return code; } +function collapsePlaceholderGoStructs(code: string): string { + const structBlockRe = /((?:\/\/.*\r?\n)*)type\s+(\w+)\s+struct\s*\{[\s\S]*?^\}/gm; + const matches = [...code.matchAll(structBlockRe)].map((match) => ({ + fullBlock: match[0], + name: match[2], + normalizedBody: normalizeGoStructBlock(match[0], match[2]), + })); + const groups = new Map(); + + for (const match of matches) { + const group = groups.get(match.normalizedBody) ?? []; + group.push(match); + groups.set(match.normalizedBody, group); + } + + for (const group of groups.values()) { + if (group.length < 2) continue; + + const canonical = chooseCanonicalPlaceholderDuplicate(group.map(({ name }) => name)); + if (!canonical) continue; + + for (const duplicate of group) { + if (duplicate.name === canonical) continue; + if (!isPlaceholderTypeName(duplicate.name)) continue; + + code = code.replace(duplicate.fullBlock, ""); + code = code.replace(new RegExp(`\\b${duplicate.name}\\b`, "g"), canonical); + } + } + + return code.replace(/\n{3,}/g, "\n\n"); +} + +function normalizeGoStructBlock(block: string, name: string): string { + return block + .replace(/^\/\/.*\r?\n/gm, "") + .replace(new RegExp(`^type\\s+${name}\\s+struct\\s*\\{`, "m"), "type struct {") + .split(/\r?\n/) + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .join("\n"); +} + +function chooseCanonicalPlaceholderDuplicate(names: string[]): string | undefined { + const specificNames = names.filter((name) => !isPlaceholderTypeName(name)); + if (specificNames.length === 0) return undefined; + return specificNames.sort((left, right) => right.length - left.length || left.localeCompare(right))[0]; +} + +function isPlaceholderTypeName(name: string): boolean { + return name.endsWith("Class"); +} + /** * Extract a mapping from (structName, jsonFieldName) → goFieldName * so the wrapper code references the actual quicktype-generated field names. @@ -117,6 +172,14 @@ function extractFieldNames(qtCode: string): Map> { return result; } +function goResultTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.result, toPascalCase(method.rpcMethod) + "Result"); +} + +function goParamsTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.params, toPascalCase(method.rpcMethod) + "Request"); +} + async function formatGoFile(filePath: string): Promise { try { await execFileAsync("go", ["fmt", filePath]); @@ -171,8 +234,7 @@ function extractGoEventVariants(schema: JSONSchema7): GoEventVariant[] { dataSchema, dataDescription: dataSchema.description, }; - }) - .filter((v) => !EXCLUDED_EVENT_TYPES.has(v.typeName)); + }); } /** @@ -277,8 +339,9 @@ function resolveGoPropertyType( // Check for discriminated union const disc = findGoDiscriminator(nonNull); if (disc) { - emitGoFlatDiscriminatedUnion(nestedName, disc.property, disc.mapping, ctx, propSchema.description); - return isRequired && !hasNull ? nestedName : `*${nestedName}`; + const unionName = (propSchema.title as string) || nestedName; + emitGoFlatDiscriminatedUnion(unionName, disc.property, disc.mapping, ctx, propSchema.description); + return isRequired && !hasNull ? unionName : `*${unionName}`; } // Non-discriminated multi-type union → any return "any"; @@ -287,7 +350,7 @@ function resolveGoPropertyType( // Handle enum if (propSchema.enum && Array.isArray(propSchema.enum)) { - const enumType = getOrCreateGoEnum(nestedName, propSchema.enum as string[], ctx, propSchema.description); + const enumType = getOrCreateGoEnum((propSchema.title as string) || nestedName, propSchema.enum as string[], ctx, propSchema.description); return isRequired ? enumType : `*${enumType}`; } @@ -335,7 +398,7 @@ function resolveGoPropertyType( const itemVariants = (items.anyOf as JSONSchema7[]).filter((v) => v.type !== "null"); const disc = findGoDiscriminator(itemVariants); if (disc) { - const itemTypeName = nestedName + "Item"; + const itemTypeName = (items.title as string) || (nestedName + "Item"); emitGoFlatDiscriminatedUnion(itemTypeName, disc.property, disc.mapping, ctx, items.description); return `[]${itemTypeName}`; } @@ -349,8 +412,9 @@ function resolveGoPropertyType( // Object type if (type === "object" || (propSchema.properties && !type)) { if (propSchema.properties && Object.keys(propSchema.properties).length > 0) { - emitGoStruct(nestedName, propSchema, ctx); - return isRequired ? nestedName : `*${nestedName}`; + const structName = (propSchema.title as string) || nestedName; + emitGoStruct(structName, propSchema, ctx); + return isRequired ? structName : `*${structName}`; } if (propSchema.additionalProperties) { if ( @@ -359,8 +423,9 @@ function resolveGoPropertyType( ) { const ap = propSchema.additionalProperties as JSONSchema7; if (ap.type === "object" && ap.properties) { - emitGoStruct(nestedName + "Value", ap, ctx); - return `map[string]${nestedName}Value`; + const valueName = (ap.title as string) || `${nestedName}Value`; + emitGoStruct(valueName, ap, ctx); + return `map[string]${valueName}`; } const valueType = resolveGoPropertyType(ap, parentTypeName, jsonPropName + "Value", true, ctx); return `map[string]${valueType}`; @@ -733,27 +798,17 @@ function generateGoSessionEventsCode(schema: JSONSchema7): string { // Type aliases for types referenced by non-generated SDK code under their short names. const TYPE_ALIASES: Record = { - PermissionRequest: "PermissionRequestedDataPermissionRequest", - PermissionRequestKind: "PermissionRequestedDataPermissionRequestKind", - PermissionRequestCommand: "PermissionRequestedDataPermissionRequestCommandsItem", - PossibleURL: "PermissionRequestedDataPermissionRequestPossibleUrlsItem", - Attachment: "UserMessageDataAttachmentsItem", - AttachmentType: "UserMessageDataAttachmentsItemType", + PermissionRequestCommand: "PermissionRequestShellCommand", + PossibleURL: "PermissionRequestShellPossibleUrl", + Attachment: "UserMessageAttachment", + AttachmentType: "UserMessageAttachmentType", }; const CONST_ALIASES: Record = { - AttachmentTypeFile: "UserMessageDataAttachmentsItemTypeFile", - AttachmentTypeDirectory: "UserMessageDataAttachmentsItemTypeDirectory", - AttachmentTypeSelection: "UserMessageDataAttachmentsItemTypeSelection", - AttachmentTypeGithubReference: "UserMessageDataAttachmentsItemTypeGithubReference", - AttachmentTypeBlob: "UserMessageDataAttachmentsItemTypeBlob", - PermissionRequestKindShell: "PermissionRequestedDataPermissionRequestKindShell", - PermissionRequestKindWrite: "PermissionRequestedDataPermissionRequestKindWrite", - PermissionRequestKindRead: "PermissionRequestedDataPermissionRequestKindRead", - PermissionRequestKindMcp: "PermissionRequestedDataPermissionRequestKindMcp", - PermissionRequestKindURL: "PermissionRequestedDataPermissionRequestKindURL", - PermissionRequestKindMemory: "PermissionRequestedDataPermissionRequestKindMemory", - PermissionRequestKindCustomTool: "PermissionRequestedDataPermissionRequestKindCustomTool", - PermissionRequestKindHook: "PermissionRequestedDataPermissionRequestKindHook", + AttachmentTypeFile: "UserMessageAttachmentTypeFile", + AttachmentTypeDirectory: "UserMessageAttachmentTypeDirectory", + AttachmentTypeSelection: "UserMessageAttachmentTypeSelection", + AttachmentTypeGithubReference: "UserMessageAttachmentTypeGithubReference", + AttachmentTypeBlob: "UserMessageAttachmentTypeBlob", }; out.push(`// Type aliases for convenience.`); out.push(`type (`); @@ -777,7 +832,7 @@ async function generateSessionEvents(schemaPath?: string): Promise { console.log("Go: generating session-events..."); const resolvedPath = schemaPath ?? (await getSessionEventsSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7); const processed = postProcessSchema(schema); const code = generateGoSessionEventsCode(processed); @@ -794,7 +849,7 @@ async function generateRpc(schemaPath?: string): Promise { console.log("Go: generating RPC types..."); const resolvedPath = schemaPath ?? (await getApiSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema); const allMethods = [ ...collectRpcMethods(schema.server || {}), @@ -809,9 +864,8 @@ async function generateRpc(schemaPath?: string): Promise { }; for (const method of allMethods) { - const baseName = toPascalCase(method.rpcMethod); if (method.result) { - combinedSchema.definitions![baseName + "Result"] = method.result; + combinedSchema.definitions![goResultTypeName(method)] = method.result; } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { // For session methods, filter out sessionId from params type @@ -824,18 +878,26 @@ async function generateRpc(schemaPath?: string): Promise { required: method.params.required?.filter((r) => r !== "sessionId"), }; if (Object.keys(filtered.properties!).length > 0) { - combinedSchema.definitions![baseName + "Params"] = filtered; + combinedSchema.definitions![goParamsTypeName(method)] = filtered; } } else { - combinedSchema.definitions![baseName + "Params"] = method.params; + combinedSchema.definitions![goParamsTypeName(method)] = method.params; } } } + const { rootDefinitions, sharedDefinitions } = hoistTitledSchemas(combinedSchema.definitions! as Record); + // Generate types via quicktype const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore()); - for (const [name, def] of Object.entries(combinedSchema.definitions!)) { - await schemaInput.addSource({ name, schema: JSON.stringify(def) }); + for (const [name, def] of Object.entries(rootDefinitions)) { + await schemaInput.addSource({ + name, + schema: JSON.stringify({ + ...def, + definitions: sharedDefinitions, + }), + }); } const inputData = new InputData(); @@ -850,14 +912,15 @@ async function generateRpc(schemaPath?: string): Promise { // Post-process quicktype output: fix enum constant names let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); qtCode = postProcessEnumConstants(qtCode); + qtCode = collapsePlaceholderGoStructs(qtCode); // Strip trailing whitespace from quicktype output (gofmt requirement) qtCode = qtCode.replace(/[ \t]+$/gm, ""); // Extract actual type names generated by quicktype (may differ from toPascalCase) const actualTypeNames = new Map(); - const structRe = /^type\s+(\w+)\s+struct\b/gm; + const typeRe = /^type\s+(\w+)\s+/gm; let sm; - while ((sm = structRe.exec(qtCode)) !== null) { + while ((sm = typeRe.exec(qtCode)) !== null) { actualTypeNames.set(sm[1].toLowerCase(), sm[1]); } const resolveType = (name: string): string => actualTypeNames.get(name.toLowerCase()) ?? name; @@ -869,10 +932,10 @@ async function generateRpc(schemaPath?: string): Promise { const experimentalTypeNames = new Set(); for (const method of allMethods) { if (method.stability !== "experimental") continue; - experimentalTypeNames.add(toPascalCase(method.rpcMethod) + "Result"); - const baseName = toPascalCase(method.rpcMethod); - if (combinedSchema.definitions![baseName + "Params"]) { - experimentalTypeNames.add(baseName + "Params"); + experimentalTypeNames.add(goResultTypeName(method)); + const paramsTypeName = goParamsTypeName(method); + if (rootDefinitions[paramsTypeName]) { + experimentalTypeNames.add(paramsTypeName); } } for (const typeName of experimentalTypeNames) { @@ -1004,13 +1067,13 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], receiver: string, name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, fieldNames: Map>, groupExperimental = false, isWrapper = false): void { const methodName = toPascalCase(name); - const resultType = resolveType(toPascalCase(method.rpcMethod) + "Result"); + const resultType = resolveType(goResultTypeName(method)); const paramProps = method.params?.properties || {}; const requiredParams = new Set(method.params?.required || []); const nonSessionParams = Object.keys(paramProps).filter((k) => k !== "sessionId"); const hasParams = isSession ? nonSessionParams.length > 0 : Object.keys(paramProps).length > 0; - const paramsType = hasParams ? resolveType(toPascalCase(method.rpcMethod) + "Params") : ""; + const paramsType = hasParams ? resolveType(goParamsTypeName(method)) : ""; // For wrapper-level methods, access fields through a.common; for service type aliases, use a directly const clientRef = isWrapper ? "a.common.client" : "a.client"; @@ -1103,9 +1166,9 @@ function emitClientSessionApiRegistration(lines: string[], clientSchema: Record< if (method.stability === "experimental" && !groupExperimental) { lines.push(`\t// Experimental: ${clientHandlerMethodName(method.rpcMethod)} is an experimental API and may change or be removed in future versions.`); } - const paramsType = resolveType(toPascalCase(method.rpcMethod) + "Params"); + const paramsType = resolveType(goParamsTypeName(method)); if (method.result) { - const resultType = resolveType(toPascalCase(method.rpcMethod) + "Result"); + const resultType = resolveType(goResultTypeName(method)); lines.push(`\t${clientHandlerMethodName(method.rpcMethod)}(request *${paramsType}) (*${resultType}, error)`); } else { lines.push(`\t${clientHandlerMethodName(method.rpcMethod)}(request *${paramsType}) error`); @@ -1140,7 +1203,7 @@ function emitClientSessionApiRegistration(lines: string[], clientSchema: Record< for (const { groupName, methods } of groups) { const handlerField = toPascalCase(groupName); for (const method of methods) { - const paramsType = resolveType(toPascalCase(method.rpcMethod) + "Params"); + const paramsType = resolveType(goParamsTypeName(method)); lines.push(`\tclient.SetRequestHandler("${method.rpcMethod}", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) {`); lines.push(`\t\tvar request ${paramsType}`); lines.push(`\t\tif err := json.Unmarshal(params, &request); err != nil {`); diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index 2aa593c5d..8c6596eee 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -10,12 +10,15 @@ import fs from "fs/promises"; import type { JSONSchema7 } from "json-schema"; import { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } from "quicktype-core"; import { + cloneSchemaForCodegen, getApiSchemaPath, + getRpcSchemaTypeName, getSessionEventsSchemaPath, + hoistTitledSchemas, + isObjectSchema, isRpcMethod, postProcessSchema, writeGeneratedFile, - isRpcMethod, isNodeFullyExperimental, type ApiSchema, type RpcMethod, @@ -118,6 +121,59 @@ function modernizePython(code: string): string { return code; } +function collapsePlaceholderPythonDataclasses(code: string): string { + const classBlockRe = /(@dataclass\r?\nclass\s+(\w+):[\s\S]*?)(?=^@dataclass|^class\s+\w+|^def\s+\w+|\Z)/gm; + const matches = [...code.matchAll(classBlockRe)].map((match) => ({ + fullBlock: match[1], + name: match[2], + normalizedBody: normalizePythonDataclassBlock(match[1], match[2]), + })); + const groups = new Map(); + + for (const match of matches) { + const group = groups.get(match.normalizedBody) ?? []; + group.push(match); + groups.set(match.normalizedBody, group); + } + + for (const group of groups.values()) { + if (group.length < 2) continue; + + const canonical = chooseCanonicalPlaceholderDuplicate(group.map(({ name }) => name)); + if (!canonical) continue; + + for (const duplicate of group) { + if (duplicate.name === canonical) continue; + if (!isPlaceholderTypeName(duplicate.name)) continue; + + code = code.replace(duplicate.fullBlock, ""); + code = code.replace(new RegExp(`\\b${duplicate.name}\\b`, "g"), canonical); + } + } + + return code.replace(/\n{3,}/g, "\n\n"); +} + +function normalizePythonDataclassBlock(block: string, name: string): string { + return block + .replace(/^@dataclass\r?\nclass\s+\w+:/, "@dataclass\nclass:") + .replace(new RegExp(`\\b${name}\\b`, "g"), "SelfType") + .split(/\r?\n/) + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .join("\n"); +} + +function chooseCanonicalPlaceholderDuplicate(names: string[]): string | undefined { + const specificNames = names.filter((name) => !isPlaceholderTypeName(name)); + if (specificNames.length === 0) return undefined; + return specificNames.sort((left, right) => right.length - left.length || left.localeCompare(right))[0]; +} + +function isPlaceholderTypeName(name: string): boolean { + return name.endsWith("Class"); +} + function toSnakeCase(s: string): string { return s .replace(/([a-z])([A-Z])/g, "$1_$2") @@ -144,13 +200,21 @@ function collectRpcMethods(node: Record): RpcMethod[] { return results; } +function pythonResultTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.result, toPascalCase(method.rpcMethod) + "Result"); +} + +function pythonParamsTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.params, toPascalCase(method.rpcMethod) + "Request"); +} + // ── Session Events ────────────────────────────────────────────────────────── async function generateSessionEvents(schemaPath?: string): Promise { console.log("Python: generating session-events..."); const resolvedPath = schemaPath ?? (await getSessionEventsSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7); const resolvedSchema = (schema.definitions?.SessionEvent as JSONSchema7) || schema; const processed = postProcessSchema(resolvedSchema); @@ -206,7 +270,7 @@ async function generateRpc(schemaPath?: string): Promise { console.log("Python: generating RPC types..."); const resolvedPath = schemaPath ?? (await getApiSchemaPath()); - const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema; + const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema); const allMethods = [ ...collectRpcMethods(schema.server || {}), @@ -221,9 +285,8 @@ async function generateRpc(schemaPath?: string): Promise { }; for (const method of allMethods) { - const baseName = toPascalCase(method.rpcMethod); if (method.result) { - combinedSchema.definitions![baseName + "Result"] = method.result; + combinedSchema.definitions![pythonResultTypeName(method)] = method.result; } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { if (method.rpcMethod.startsWith("session.")) { @@ -235,18 +298,26 @@ async function generateRpc(schemaPath?: string): Promise { required: method.params.required?.filter((r) => r !== "sessionId"), }; if (Object.keys(filtered.properties!).length > 0) { - combinedSchema.definitions![baseName + "Params"] = filtered; + combinedSchema.definitions![pythonParamsTypeName(method)] = filtered; } } else { - combinedSchema.definitions![baseName + "Params"] = method.params; + combinedSchema.definitions![pythonParamsTypeName(method)] = method.params; } } } + const { rootDefinitions, sharedDefinitions } = hoistTitledSchemas(combinedSchema.definitions! as Record); + // Generate types via quicktype const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore()); - for (const [name, def] of Object.entries(combinedSchema.definitions!)) { - await schemaInput.addSource({ name, schema: JSON.stringify(def) }); + for (const [name, def] of Object.entries(rootDefinitions)) { + await schemaInput.addSource({ + name, + schema: JSON.stringify({ + ...def, + definitions: sharedDefinitions, + }), + }); } const inputData = new InputData(); @@ -267,15 +338,16 @@ async function generateRpc(schemaPath?: string): Promise { typesCode = typesCode.replace(/^(\s*)pass\n\n(\s*@staticmethod)/gm, "$2"); // Modernize to Python 3.11+ syntax typesCode = modernizePython(typesCode); + typesCode = collapsePlaceholderPythonDataclasses(typesCode); // Annotate experimental data types const experimentalTypeNames = new Set(); for (const method of allMethods) { if (method.stability !== "experimental") continue; - experimentalTypeNames.add(toPascalCase(method.rpcMethod) + "Result"); - const baseName = toPascalCase(method.rpcMethod); - if (combinedSchema.definitions![baseName + "Params"]) { - experimentalTypeNames.add(baseName + "Params"); + experimentalTypeNames.add(pythonResultTypeName(method)); + const paramsTypeName = pythonParamsTypeName(method); + if (rootDefinitions[paramsTypeName]) { + experimentalTypeNames.add(paramsTypeName); } } for (const typeName of experimentalTypeNames) { @@ -402,12 +474,13 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, groupExperimental = false): void { const methodName = toSnakeCase(name); - const resultType = resolveType(toPascalCase(method.rpcMethod) + "Result"); + const resultType = resolveType(pythonResultTypeName(method)); + const resultIsObject = isObjectSchema(method.result); const paramProps = method.params?.properties || {}; const nonSessionParams = Object.keys(paramProps).filter((k) => k !== "sessionId"); const hasParams = isSession ? nonSessionParams.length > 0 : Object.keys(paramProps).length > 0; - const paramsType = resolveType(toPascalCase(method.rpcMethod) + "Params"); + const paramsType = resolveType(pythonParamsTypeName(method)); // Build signature with typed params + optional timeout const sig = hasParams @@ -420,21 +493,24 @@ function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: lines.push(` """.. warning:: This API is experimental and may change or be removed in future versions."""`); } + // For object results use .from_dict(); for enums/primitives use direct construction + const deserialize = (expr: string) => resultIsObject ? `${resultType}.from_dict(${expr})` : `${resultType}(${expr})`; + // Build request body with proper serialization/deserialization if (isSession) { if (hasParams) { lines.push(` params_dict = {k: v for k, v in params.to_dict().items() if v is not None}`); lines.push(` params_dict["sessionId"] = self._session_id`); - lines.push(` return ${resultType}.from_dict(await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout)))`); + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); } else { - lines.push(` return ${resultType}.from_dict(await self._client.request("${method.rpcMethod}", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))`); + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))`)}`); } } else { if (hasParams) { lines.push(` params_dict = {k: v for k, v in params.to_dict().items() if v is not None}`); - lines.push(` return ${resultType}.from_dict(await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout)))`); + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); } else { - lines.push(` return ${resultType}.from_dict(await self._client.request("${method.rpcMethod}", {}, **_timeout_kwargs(timeout)))`); + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {}, **_timeout_kwargs(timeout))`)}`); } } lines.push(``); @@ -503,8 +579,8 @@ function emitClientSessionHandlerMethod( resolveType: (name: string) => string, groupExperimental = false ): void { - const paramsType = resolveType(toPascalCase(method.rpcMethod) + "Params"); - const resultType = method.result ? resolveType(toPascalCase(method.rpcMethod) + "Result") : "None"; + const paramsType = resolveType(pythonParamsTypeName(method)); + const resultType = method.result ? resolveType(pythonResultTypeName(method)) : "None"; lines.push(` async def ${toSnakeCase(name)}(self, params: ${paramsType}) -> ${resultType}:`); if (method.stability === "experimental" && !groupExperimental) { lines.push(` """.. warning:: This API is experimental and may change or be removed in future versions."""`); @@ -520,8 +596,8 @@ function emitClientSessionRegistrationMethod( resolveType: (name: string) => string ): void { const handlerVariableName = `handle_${toSnakeCase(groupName)}_${toSnakeCase(methodName)}`; - const paramsType = resolveType(toPascalCase(method.rpcMethod) + "Params"); - const resultType = method.result ? resolveType(toPascalCase(method.rpcMethod) + "Result") : null; + const paramsType = resolveType(pythonParamsTypeName(method)); + const resultType = method.result ? resolveType(pythonResultTypeName(method)) : null; const handlerField = toSnakeCase(groupName); const handlerMethod = toSnakeCase(methodName); @@ -533,7 +609,11 @@ function emitClientSessionRegistrationMethod( ); if (resultType) { lines.push(` result = await handler.${handlerMethod}(request)`); - lines.push(` return result.to_dict()`); + if (isObjectSchema(method.result)) { + lines.push(` return result.to_dict()`); + } else { + lines.push(` return result.value if hasattr(result, 'value') else result`); + } } else { lines.push(` await handler.${handlerMethod}(request)`); lines.push(` return None`); diff --git a/scripts/codegen/typescript.ts b/scripts/codegen/typescript.ts index e5e82bdc6..c2b01f7b4 100644 --- a/scripts/codegen/typescript.ts +++ b/scripts/codegen/typescript.ts @@ -10,22 +10,108 @@ import fs from "fs/promises"; import type { JSONSchema7 } from "json-schema"; import { compile } from "json-schema-to-typescript"; import { - getSessionEventsSchemaPath, getApiSchemaPath, + getRpcSchemaTypeName, + getSessionEventsSchemaPath, + isNodeFullyExperimental, + isRpcMethod, postProcessSchema, + stripNonAnnotationTitles, writeGeneratedFile, - isRpcMethod, - isNodeFullyExperimental, type ApiSchema, type RpcMethod, } from "./utils.js"; -// ── Utilities ─────────────────────────────────────────────────────────────── - function toPascalCase(s: string): string { return s.charAt(0).toUpperCase() + s.slice(1); } +function appendUniqueExportBlocks(output: string[], compiled: string, seenBlocks: Map): void { + for (const block of splitExportBlocks(compiled)) { + const nameMatch = /^export\s+(?:interface|type)\s+(\w+)/m.exec(block); + if (!nameMatch) { + output.push(block); + continue; + } + + const name = nameMatch[1]; + const normalizedBlock = normalizeExportBlock(block); + const existing = seenBlocks.get(name); + if (existing) { + if (existing !== normalizedBlock) { + throw new Error(`Duplicate generated TypeScript declaration for "${name}" with different content.`); + } + continue; + } + + seenBlocks.set(name, normalizedBlock); + output.push(block); + } +} + +function splitExportBlocks(compiled: string): string[] { + const normalizedCompiled = compiled + .trim() + .replace(/;(export\s+(?:interface|type)\s+)/g, ";\n$1") + .replace(/}(export\s+(?:interface|type)\s+)/g, "}\n$1"); + const lines = normalizedCompiled.split(/\r?\n/); + const blocks: string[] = []; + let pending: string[] = []; + + for (let index = 0; index < lines.length;) { + const line = lines[index]; + if (!/^export\s+(?:interface|type)\s+\w+/.test(line)) { + pending.push(line); + index++; + continue; + } + + const blockLines = [...pending, line]; + pending = []; + let braceDepth = countBraces(line); + index++; + + if (braceDepth === 0 && line.trim().endsWith(";")) { + blocks.push(blockLines.join("\n").trim()); + continue; + } + + while (index < lines.length) { + const nextLine = lines[index]; + blockLines.push(nextLine); + braceDepth += countBraces(nextLine); + index++; + + const trimmed = nextLine.trim(); + if (braceDepth === 0 && (trimmed === "}" || trimmed.endsWith(";"))) { + break; + } + } + + blocks.push(blockLines.join("\n").trim()); + } + + return blocks; +} + +function countBraces(line: string): number { + let depth = 0; + for (const char of line) { + if (char === "{") depth++; + if (char === "}") depth--; + } + return depth; +} + +function normalizeExportBlock(block: string): string { + return block + .replace(/\/\*\*[\s\S]*?\*\//g, "") + .split(/\r?\n/) + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .join("\n"); +} + function collectRpcMethods(node: Record): RpcMethod[] { const results: RpcMethod[] = []; for (const value of Object.values(node)) { @@ -45,7 +131,7 @@ async function generateSessionEvents(schemaPath?: string): Promise { const resolvedPath = schemaPath ?? (await getSessionEventsSchemaPath()); const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as JSONSchema7; - const processed = postProcessSchema(schema); + const processed = postProcessSchema(stripNonAnnotationTitles(schema)); const ts = await compile(processed, "SessionEvent", { bannerComment: `/** @@ -62,12 +148,12 @@ async function generateSessionEvents(schemaPath?: string): Promise { // ── RPC Types ─────────────────────────────────────────────────────────────── -function resultTypeName(rpcMethod: string): string { - return rpcMethod.split(".").map(toPascalCase).join("") + "Result"; +function resultTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.result, method.rpcMethod.split(".").map(toPascalCase).join("") + "Result"); } -function paramsTypeName(rpcMethod: string): string { - return rpcMethod.split(".").map(toPascalCase).join("") + "Params"; +function paramsTypeName(method: RpcMethod): string { + return getRpcSchemaTypeName(method.params, method.rpcMethod.split(".").map(toPascalCase).join("") + "Request"); } async function generateRpc(schemaPath?: string): Promise { @@ -87,29 +173,30 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; const allMethods = [...collectRpcMethods(schema.server || {}), ...collectRpcMethods(schema.session || {})]; const clientSessionMethods = collectRpcMethods(schema.clientSession || {}); + const seenBlocks = new Map(); for (const method of [...allMethods, ...clientSessionMethods]) { if (method.result) { - const compiled = await compile(method.result, resultTypeName(method.rpcMethod), { + const compiled = await compile(stripNonAnnotationTitles(method.result), resultTypeName(method), { bannerComment: "", additionalProperties: false, }); if (method.stability === "experimental") { lines.push("/** @experimental */"); } - lines.push(compiled.trim()); + appendUniqueExportBlocks(lines, compiled, seenBlocks); lines.push(""); } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { - const paramsCompiled = await compile(method.params, paramsTypeName(method.rpcMethod), { + const paramsCompiled = await compile(stripNonAnnotationTitles(method.params), paramsTypeName(method), { bannerComment: "", additionalProperties: false, }); if (method.stability === "experimental") { lines.push("/** @experimental */"); } - lines.push(paramsCompiled.trim()); + appendUniqueExportBlocks(lines, paramsCompiled, seenBlocks); lines.push(""); } } @@ -149,8 +236,8 @@ function emitGroup(node: Record, indent: string, isSession: boo for (const [key, value] of Object.entries(node)) { if (isRpcMethod(value)) { const { rpcMethod, params } = value; - const resultType = value.result ? resultTypeName(rpcMethod) : "void"; - const paramsType = paramsTypeName(rpcMethod); + const resultType = value.result ? resultTypeName(value) : "void"; + const paramsType = paramsTypeName(value); const paramEntries = params?.properties ? Object.entries(params.properties).filter(([k]) => k !== "sessionId") : []; const hasParams = params?.properties && Object.keys(params.properties).length > 0; @@ -238,8 +325,8 @@ function emitClientSessionApiRegistration(clientSchema: Record) for (const method of methods) { const name = handlerMethodName(method.rpcMethod); const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; - const pType = hasParams ? paramsTypeName(method.rpcMethod) : ""; - const rType = method.result ? resultTypeName(method.rpcMethod) : "void"; + const pType = hasParams ? paramsTypeName(method) : ""; + const rType = method.result ? resultTypeName(method) : "void"; if (hasParams) { lines.push(` ${name}(params: ${pType}): Promise<${rType}>;`); @@ -276,7 +363,7 @@ function emitClientSessionApiRegistration(clientSchema: Record) for (const [groupName, methods] of groups) { for (const method of methods) { const name = handlerMethodName(method.rpcMethod); - const pType = paramsTypeName(method.rpcMethod); + const pType = paramsTypeName(method); const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; if (hasParams) { diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index 1e95b4dd4..6fd1a617e 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -21,9 +21,6 @@ const __dirname = path.dirname(__filename); /** Root of the copilot-sdk repo */ export const REPO_ROOT = path.resolve(__dirname, "../.."); -/** Event types to exclude from generation (internal/legacy types) */ -export const EXCLUDED_EVENT_TYPES = new Set(["session.import_legacy"]); - // ── Schema paths ──────────────────────────────────────────────────────────── export async function getSessionEventsSchemaPath(): Promise { @@ -49,7 +46,7 @@ export async function getApiSchemaPath(cliArg?: string): Promise { /** * Post-process JSON Schema for quicktype compatibility. - * Converts boolean const values to enum, filters excluded event types. + * Converts boolean const values to enum. */ export function postProcessSchema(schema: JSONSchema7): JSONSchema7 { if (typeof schema !== "object" || schema === null) return schema; @@ -81,18 +78,9 @@ export function postProcessSchema(schema: JSONSchema7): JSONSchema7 { for (const combiner of ["anyOf", "allOf", "oneOf"] as const) { if (processed[combiner]) { - processed[combiner] = processed[combiner]! - .filter((item) => { - if (typeof item !== "object") return true; - const typeConst = (item as JSONSchema7).properties?.type; - if (typeof typeConst === "object" && "const" in typeConst) { - return !EXCLUDED_EVENT_TYPES.has(typeConst.const as string); - } - return true; - }) - .map((item) => - typeof item === "object" ? postProcessSchema(item as JSONSchema7) : item - ) as JSONSchema7Definition[]; + processed[combiner] = processed[combiner]!.map((item) => + typeof item === "object" ? postProcessSchema(item as JSONSchema7) : item + ) as JSONSchema7Definition[]; } } @@ -129,6 +117,160 @@ export interface RpcMethod { stability?: string; } +export function getRpcSchemaTypeName(schema: JSONSchema7 | null | undefined, fallback: string): string { + if (typeof schema?.title === "string") return schema.title; + return fallback; +} + +/** + * Returns true if the schema represents an object with properties (i.e., a type that should + * be generated as a class/struct/dataclass). Returns false for enums, primitives, arrays, + * and other non-object schemas. + */ +export function isObjectSchema(schema: JSONSchema7 | null | undefined): boolean { + if (!schema) return false; + if (schema.type === "object" && schema.properties) return true; + return false; +} + +export function cloneSchemaForCodegen(value: T): T { + if (Array.isArray(value)) { + return value.map((item) => cloneSchemaForCodegen(item)) as T; + } + + if (value && typeof value === "object") { + const result: Record = {}; + for (const [key, child] of Object.entries(value as Record)) { + if (key === "titleSource") { + continue; + } + result[key] = cloneSchemaForCodegen(child); + } + + return result as T; + } + + return value; +} + +export function stripNonAnnotationTitles(value: T): T { + if (Array.isArray(value)) { + return value.map((item) => stripNonAnnotationTitles(item)) as T; + } + + if (value && typeof value === "object") { + const result: Record = {}; + const source = value as Record; + const keepTitle = typeof source.title === "string" && source.titleSource === "annotation"; + for (const [key, child] of Object.entries(source)) { + if (key === "titleSource") { + continue; + } + if (key === "title" && !keepTitle) { + continue; + } + result[key] = stripNonAnnotationTitles(child); + } + + return result as T; + } + + return value; +} + +export function hoistTitledSchemas( + rootDefinitions: Record +): { rootDefinitions: Record; sharedDefinitions: Record } { + const sharedDefinitions: Record = {}; + const processedRoots: Record = {}; + + for (const [rootName, definition] of Object.entries(rootDefinitions)) { + processedRoots[rootName] = visitSchema(definition, rootName, sharedDefinitions); + } + + return { rootDefinitions: processedRoots, sharedDefinitions }; +} + +function visitSchema( + schema: JSONSchema7, + rootName: string, + sharedDefinitions: Record +): JSONSchema7 { + const result: JSONSchema7 = { ...schema }; + + if (result.properties) { + result.properties = Object.fromEntries( + Object.entries(result.properties).map(([key, value]) => [ + key, + typeof value === "object" && value !== null && !Array.isArray(value) + ? visitSchema(value as JSONSchema7, rootName, sharedDefinitions) + : value, + ]) + ); + } + + if (result.items) { + if (Array.isArray(result.items)) { + result.items = result.items.map((item) => + typeof item === "object" && item !== null && !Array.isArray(item) + ? visitSchema(item as JSONSchema7, rootName, sharedDefinitions) + : item + ) as JSONSchema7Definition[]; + } else if (typeof result.items === "object" && result.items !== null) { + result.items = visitSchema(result.items as JSONSchema7, rootName, sharedDefinitions); + } + } + + if (typeof result.additionalProperties === "object" && result.additionalProperties !== null) { + result.additionalProperties = visitSchema(result.additionalProperties as JSONSchema7, rootName, sharedDefinitions); + } + + for (const combiner of ["anyOf", "allOf", "oneOf"] as const) { + if (result[combiner]) { + result[combiner] = result[combiner]!.map((item) => + typeof item === "object" && item !== null && !Array.isArray(item) + ? visitSchema(item as JSONSchema7, rootName, sharedDefinitions) + : item + ) as JSONSchema7Definition[]; + } + } + + if (typeof result.title === "string" && result.title !== rootName) { + const existing = sharedDefinitions[result.title]; + if (existing) { + if (stableStringify(existing) !== stableStringify(result)) { + throw new Error(`Conflicting titled schemas for "${result.title}" while preparing quicktype inputs.`); + } + } else { + sharedDefinitions[result.title] = result; + } + return { $ref: `#/definitions/${result.title}` }; + } + + return result; +} + +function stableStringify(value: unknown): string { + return JSON.stringify(sortJsonValue(value)); +} + +function sortJsonValue(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(sortJsonValue); + } + + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value as Record) + .filter(([key]) => key !== "description" && key !== "titleSource") + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, child]) => [key, sortJsonValue(child)]) + ); + } + + return value; +} + export interface ApiSchema { server?: Record; session?: Record; diff --git a/test/scenarios/prompts/attachments/csharp/Program.cs b/test/scenarios/prompts/attachments/csharp/Program.cs index 357444a6f..272c89aab 100644 --- a/test/scenarios/prompts/attachments/csharp/Program.cs +++ b/test/scenarios/prompts/attachments/csharp/Program.cs @@ -24,7 +24,7 @@ Prompt = "What languages are listed in the attached file?", Attachments = [ - new UserMessageDataAttachmentsItemFile { Path = sampleFile, DisplayName = "sample-data.txt" }, + new UserMessageAttachmentFile { Path = sampleFile, DisplayName = "sample-data.txt" }, ], }); diff --git a/test/snapshots/agent_and_compact_rpc/should_compact_session_history_after_messages.yaml b/test/snapshots/agent_and_compact_rpc/should_compact_session_history_after_messages.yaml index fa5cf614a..a13727f0f 100644 --- a/test/snapshots/agent_and_compact_rpc/should_compact_session_history_after_messages.yaml +++ b/test/snapshots/agent_and_compact_rpc/should_compact_session_history_after_messages.yaml @@ -14,9 +14,9 @@ conversations: content: >- - The user asked a simple arithmetic question ("What is 2+2?") which was answered directly (4). No technical - work, code changes, or file modifications were requested or performed. This appears to be a minimal test or - verification exchange before any substantive work begins. + The user asked a simple arithmetic question: "What is 2+2?" This was answered directly (4). No technical work, + coding tasks, or file modifications were performed. This appears to have been a minimal test interaction with + no substantive goals or technical requirements. @@ -25,54 +25,39 @@ conversations: 1. The user asked "What is 2+2?" - Provided the answer: 4 - - No follow-up actions were needed + - No further actions were taken or requested - No work has been performed. No files were created, modified, or deleted. This was purely an informational - exchange with no code changes or system modifications. + No files were created, modified, or deleted. No technical tasks were performed. The conversation consisted + solely of answering a basic arithmetic question. - Current state: - - - Working directory: ${workdir} - - - Not a git repository - - - No files have been accessed or modified - - - No todos or plan have been created + Current state: No active work in progress. - - Environment is Windows (Windows_NT), requiring backslash path separators - - - Session workspace available for artifacts (e.g., plan.md) - - - SQL database available but not yet initialized (no tables created) - - - Available tools: git, curl, gh - - - No technical work has been performed yet, so no technical details have been discovered + No technical concepts, decisions, or issues were encountered in this conversation. This was a straightforward + arithmetic question with no technical context. - No files have been accessed or modified during this conversation. + No files were involved in this conversation. - No work is currently in progress. Awaiting user's next request for any substantive task. + No pending work or tasks. The user's question was fully addressed. Awaiting new requests or instructions. diff --git a/test/snapshots/session_fs/should_succeed_with_compaction_while_using_sessionfs.yaml b/test/snapshots/session_fs/should_succeed_with_compaction_while_using_sessionfs.yaml index 2b984d74c..d942e7ab1 100644 --- a/test/snapshots/session_fs/should_succeed_with_compaction_while_using_sessionfs.yaml +++ b/test/snapshots/session_fs/should_succeed_with_compaction_while_using_sessionfs.yaml @@ -14,9 +14,9 @@ conversations: content: >- - The user asked a simple arithmetic question ("What is 2+2?"). This was a minimal interaction with no technical - work, coding tasks, or file modifications requested or performed. The conversation consisted solely of - providing a basic mathematical answer. + The user asked a simple arithmetic question ("What is 2+2?") which I answered correctly (4). No coding work, + file modifications, or technical implementation was requested or performed. This appears to be a minimal test + interaction before the conversation history is compacted. @@ -24,52 +24,46 @@ conversations: 1. The user asked "What is 2+2?" - - Provided the answer: 4 - - No further requests or actions were needed + - I provided the arithmetic answer: 4 + - No follow-up questions or additional requests were made - 2. The user requested a checkpoint summary - - Creating this summary to preserve conversation context before history compaction + 2. The user requested a detailed summary for conversation compaction + - Currently preparing this checkpoint summary - No files were created, modified, or deleted. No technical work was performed. The conversation consisted only - of answering a simple arithmetic question. + No files were created, modified, or deleted. No code changes were made. No tasks were assigned or completed + beyond answering a basic arithmetic question. - Current state: - - - No active tasks - - - No code changes - - - No systems or processes started + Current state: No active work in progress. The conversation consisted only of a single question and answer + exchange. - No technical work was performed during this conversation. No technical decisions, issues, or discoveries were - made. + No technical work was performed. No issues were encountered. No architectural decisions were made. No code was + explored or modified. - No files are relevant to this conversation, as no technical work was performed. + No files were accessed or are relevant to this conversation. - No pending work or next steps. The user's request (answering "2+2") has been completed. Awaiting further - instructions from the user. + No pending work. No tasks were assigned. The user may continue with new requests after the history compaction. - Simple arithmetic question answered + Answered arithmetic question From 33ce54432971ef2d3ce2ec79d6d7c1f5f3db54e8 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 12:04:28 +0100 Subject: [PATCH 02/18] Make codegen able to handle void-result RPC methods Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- scripts/codegen/csharp.ts | 32 +++++++++++++++++++++++--------- scripts/codegen/go.ts | 28 +++++++++++++++++++--------- scripts/codegen/python.ts | 27 ++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 2cf01d499..566ba8df0 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -952,8 +952,8 @@ function emitServerInstanceMethod( groupExperimental: boolean ): void { const methodName = toPascalCase(name); - let resultClassName = resultTypeName(method); - if (method.stability === "experimental") { + let resultClassName = method.result ? resultTypeName(method) : ""; + if (method.result && method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } if (isObjectSchema(method.result)) { @@ -1003,13 +1003,22 @@ function emitServerInstanceMethod( } sigParams.push("CancellationToken cancellationToken = default"); - lines.push(`${indent}public async Task<${resultClassName}> ${methodName}Async(${sigParams.join(", ")})`); + const taskType = method.result ? `Task<${resultClassName}>` : "Task"; + lines.push(`${indent}public async ${taskType} ${methodName}Async(${sigParams.join(", ")})`); lines.push(`${indent}{`); if (requestClassName && bodyAssignments.length > 0) { lines.push(`${indent} var request = new ${requestClassName} { ${bodyAssignments.join(", ")} };`); - lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`); + if (method.result) { + lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`); + } else { + lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [request], cancellationToken);`); + } } else { - lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [], cancellationToken);`); + if (method.result) { + lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [], cancellationToken);`); + } else { + lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [], cancellationToken);`); + } } lines.push(`${indent}}`); } @@ -1043,8 +1052,8 @@ function emitSessionRpcClasses(node: Record, classes: string[]) function emitSessionMethod(key: string, method: RpcMethod, lines: string[], classes: string[], indent: string, groupExperimental: boolean): void { const methodName = toPascalCase(key); - let resultClassName = resultTypeName(method); - if (method.stability === "experimental") { + let resultClassName = method.result ? resultTypeName(method) : ""; + if (method.result && method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } if (isObjectSchema(method.result)) { @@ -1089,9 +1098,14 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas } sigParams.push("CancellationToken cancellationToken = default"); - lines.push(`${indent}public async Task<${resultClassName}> ${methodName}Async(${sigParams.join(", ")})`); + const taskType = method.result ? `Task<${resultClassName}>` : "Task"; + lines.push(`${indent}public async ${taskType} ${methodName}Async(${sigParams.join(", ")})`); lines.push(`${indent}{`, `${indent} var request = new ${requestClassName} { ${bodyAssignments.join(", ")} };`); - lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`, `${indent}}`); + if (method.result) { + lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`, `${indent}}`); + } else { + lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [request], cancellationToken);`, `${indent}}`); + } } function emitSessionApiClass(className: string, node: Record, classes: string[]): string { diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 70a137bfb..6c1121304 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -1067,7 +1067,8 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], receiver: string, name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, fieldNames: Map>, groupExperimental = false, isWrapper = false): void { const methodName = toPascalCase(name); - const resultType = resolveType(goResultTypeName(method)); + const hasResult = !!method.result; + const resultType = hasResult ? resolveType(goResultTypeName(method)) : ""; const paramProps = method.params?.properties || {}; const requiredParams = new Set(method.params?.required || []); @@ -1082,12 +1083,16 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc if (method.stability === "experimental" && !groupExperimental) { lines.push(`// Experimental: ${methodName} is an experimental API and may change or be removed in future versions.`); } + + const returnType = hasResult ? `(*${resultType}, error)` : `error`; const sig = hasParams - ? `func (a *${receiver}) ${methodName}(ctx context.Context, params *${paramsType}) (*${resultType}, error)` - : `func (a *${receiver}) ${methodName}(ctx context.Context) (*${resultType}, error)`; + ? `func (a *${receiver}) ${methodName}(ctx context.Context, params *${paramsType}) ${returnType}` + : `func (a *${receiver}) ${methodName}(ctx context.Context) ${returnType}`; lines.push(sig + ` {`); + const errReturn = hasResult ? `return nil, err` : `return err`; + if (isSession) { lines.push(`\treq := map[string]any{"sessionId": ${sessionIDRef}}`); if (hasParams) { @@ -1113,13 +1118,18 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc } lines.push(`\tif err != nil {`); - lines.push(`\t\treturn nil, err`); - lines.push(`\t}`); - lines.push(`\tvar result ${resultType}`); - lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil {`); - lines.push(`\t\treturn nil, err`); + lines.push(`\t\t${errReturn}`); lines.push(`\t}`); - lines.push(`\treturn &result, nil`); + + if (hasResult) { + lines.push(`\tvar result ${resultType}`); + lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil {`); + lines.push(`\t\treturn nil, err`); + lines.push(`\t}`); + lines.push(`\treturn &result, nil`); + } else { + lines.push(`\treturn nil`); + } lines.push(`}`); lines.push(``); } diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index 8c6596eee..ac81b2d3c 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -474,7 +474,8 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, groupExperimental = false): void { const methodName = toSnakeCase(name); - const resultType = resolveType(pythonResultTypeName(method)); + const hasResult = !!method.result; + const resultType = hasResult ? resolveType(pythonResultTypeName(method)) : "None"; const resultIsObject = isObjectSchema(method.result); const paramProps = method.params?.properties || {}; @@ -501,16 +502,32 @@ function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: if (hasParams) { lines.push(` params_dict = {k: v for k, v in params.to_dict().items() if v is not None}`); lines.push(` params_dict["sessionId"] = self._session_id`); - lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); + if (hasResult) { + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); + } else { + lines.push(` await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`); + } } else { - lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))`)}`); + if (hasResult) { + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))`)}`); + } else { + lines.push(` await self._client.request("${method.rpcMethod}", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))`); + } } } else { if (hasParams) { lines.push(` params_dict = {k: v for k, v in params.to_dict().items() if v is not None}`); - lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); + if (hasResult) { + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`)}`); + } else { + lines.push(` await self._client.request("${method.rpcMethod}", params_dict, **_timeout_kwargs(timeout))`); + } } else { - lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {}, **_timeout_kwargs(timeout))`)}`); + if (hasResult) { + lines.push(` return ${deserialize(`await self._client.request("${method.rpcMethod}", {}, **_timeout_kwargs(timeout))`)}`); + } else { + lines.push(` await self._client.request("${method.rpcMethod}", {}, **_timeout_kwargs(timeout))`); + } } } lines.push(``); From 0efd328fd5193f7dd49c4d36b95a513a8ec73da6 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 12:14:00 +0100 Subject: [PATCH 03/18] In Go, buy some more forward-compat by ensuring RPC methods never return void Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- go/rpc/generated_rpc.go | 79 +++++++++++++++++++++++++++++++++-------- scripts/codegen/go.ts | 64 ++++++++++++--------------------- 2 files changed, 87 insertions(+), 56 deletions(-) diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 90925defb..21756a2a4 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -164,6 +164,9 @@ type MCPConfigServer struct { URL *string `json:"url,omitempty"` } +type MCPConfigAddResult struct { +} + type MCPConfigAddRequest struct { Config MCPConfigAddConfig `json:"config"` // Unique name for the MCP server @@ -189,6 +192,9 @@ type MCPConfigAddConfig struct { URL *string `json:"url,omitempty"` } +type MCPConfigUpdateResult struct { +} + type MCPConfigUpdateRequest struct { Config MCPConfigUpdateConfig `json:"config"` // Name of the MCP server to update @@ -214,6 +220,9 @@ type MCPConfigUpdateConfig struct { URL *string `json:"url,omitempty"` } +type MCPConfigRemoveResult struct { +} + type MCPConfigRemoveRequest struct { // Name of the MCP server to remove Name string `json:"name"` @@ -873,6 +882,9 @@ type SessionFSReadFileRequest struct { SessionID string `json:"sessionId"` } +type SessionFSWriteFileResult struct { +} + type SessionFSWriteFileRequest struct { // Content to write Content string `json:"content"` @@ -884,6 +896,9 @@ type SessionFSWriteFileRequest struct { SessionID string `json:"sessionId"` } +type SessionFSAppendFileResult struct { +} + type SessionFSAppendFileRequest struct { // Content to append Content string `json:"content"` @@ -927,6 +942,9 @@ type SessionFSStatRequest struct { SessionID string `json:"sessionId"` } +type SessionFSMkdirResult struct { +} + type SessionFSMkdirRequest struct { // Optional POSIX-style mode for newly created directories Mode *int64 `json:"mode,omitempty"` @@ -968,6 +986,9 @@ type SessionFSReaddirWithTypesRequest struct { SessionID string `json:"sessionId"` } +type SessionFSRmResult struct { +} + type SessionFSRmRequest struct { // Ignore errors if the path does not exist Force *bool `json:"force,omitempty"` @@ -979,6 +1000,9 @@ type SessionFSRmRequest struct { SessionID string `json:"sessionId"` } +type SessionFSRenameResult struct { +} + type SessionFSRenameRequest struct { // Destination path using SessionFs conventions Dest string `json:"dest"` @@ -2015,15 +2039,15 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { type SessionFsHandler interface { ReadFile(request *SessionFSReadFileRequest) (*SessionFSReadFileResult, error) - WriteFile(request *SessionFSWriteFileRequest) error - AppendFile(request *SessionFSAppendFileRequest) error + WriteFile(request *SessionFSWriteFileRequest) (*SessionFSWriteFileResult, error) + AppendFile(request *SessionFSAppendFileRequest) (*SessionFSAppendFileResult, error) Exists(request *SessionFSExistsRequest) (*SessionFSExistsResult, error) Stat(request *SessionFSStatRequest) (*SessionFSStatResult, error) - Mkdir(request *SessionFSMkdirRequest) error + Mkdir(request *SessionFSMkdirRequest) (*SessionFSMkdirResult, error) Readdir(request *SessionFSReaddirRequest) (*SessionFSReaddirResult, error) ReaddirWithTypes(request *SessionFSReaddirWithTypesRequest) (*SessionFSReaddirWithTypesResult, error) - Rm(request *SessionFSRmRequest) error - Rename(request *SessionFSRenameRequest) error + Rm(request *SessionFSRmRequest) (*SessionFSRmResult, error) + Rename(request *SessionFSRenameRequest) (*SessionFSRenameResult, error) } // ClientSessionApiHandlers provides all client session API handler groups for a session. @@ -2072,10 +2096,15 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( if handlers == nil || handlers.SessionFs == nil { return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No sessionFs handler registered for session: %s", request.SessionID)} } - if err := handlers.SessionFs.WriteFile(&request); err != nil { + result, err := handlers.SessionFs.WriteFile(&request) + if err != nil { return nil, clientSessionHandlerError(err) } - return json.RawMessage("null"), nil + raw, err := json.Marshal(result) + if err != nil { + return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)} + } + return raw, nil }) client.SetRequestHandler("sessionFs.appendFile", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { var request SessionFSAppendFileRequest @@ -2086,10 +2115,15 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( if handlers == nil || handlers.SessionFs == nil { return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No sessionFs handler registered for session: %s", request.SessionID)} } - if err := handlers.SessionFs.AppendFile(&request); err != nil { + result, err := handlers.SessionFs.AppendFile(&request) + if err != nil { return nil, clientSessionHandlerError(err) } - return json.RawMessage("null"), nil + raw, err := json.Marshal(result) + if err != nil { + return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)} + } + return raw, nil }) client.SetRequestHandler("sessionFs.exists", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { var request SessionFSExistsRequest @@ -2138,10 +2172,15 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( if handlers == nil || handlers.SessionFs == nil { return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No sessionFs handler registered for session: %s", request.SessionID)} } - if err := handlers.SessionFs.Mkdir(&request); err != nil { + result, err := handlers.SessionFs.Mkdir(&request) + if err != nil { return nil, clientSessionHandlerError(err) } - return json.RawMessage("null"), nil + raw, err := json.Marshal(result) + if err != nil { + return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)} + } + return raw, nil }) client.SetRequestHandler("sessionFs.readdir", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { var request SessionFSReaddirRequest @@ -2190,10 +2229,15 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( if handlers == nil || handlers.SessionFs == nil { return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No sessionFs handler registered for session: %s", request.SessionID)} } - if err := handlers.SessionFs.Rm(&request); err != nil { + result, err := handlers.SessionFs.Rm(&request) + if err != nil { return nil, clientSessionHandlerError(err) } - return json.RawMessage("null"), nil + raw, err := json.Marshal(result) + if err != nil { + return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)} + } + return raw, nil }) client.SetRequestHandler("sessionFs.rename", func(params json.RawMessage) (json.RawMessage, *jsonrpc2.Error) { var request SessionFSRenameRequest @@ -2204,9 +2248,14 @@ func RegisterClientSessionApiHandlers(client *jsonrpc2.Client, getHandlers func( if handlers == nil || handlers.SessionFs == nil { return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No sessionFs handler registered for session: %s", request.SessionID)} } - if err := handlers.SessionFs.Rename(&request); err != nil { + result, err := handlers.SessionFs.Rename(&request) + if err != nil { return nil, clientSessionHandlerError(err) } - return json.RawMessage("null"), nil + raw, err := json.Marshal(result) + if err != nil { + return nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)} + } + return raw, nil }) } diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 6c1121304..2e3a55b91 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -866,6 +866,9 @@ async function generateRpc(schemaPath?: string): Promise { for (const method of allMethods) { if (method.result) { combinedSchema.definitions![goResultTypeName(method)] = method.result; + } else { + // Emit an empty struct for void results (forward-compatible with adding fields later) + combinedSchema.definitions![goResultTypeName(method)] = { type: "object", properties: {}, additionalProperties: false }; } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { // For session methods, filter out sessionId from params type @@ -1067,8 +1070,7 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], receiver: string, name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, fieldNames: Map>, groupExperimental = false, isWrapper = false): void { const methodName = toPascalCase(name); - const hasResult = !!method.result; - const resultType = hasResult ? resolveType(goResultTypeName(method)) : ""; + const resultType = resolveType(goResultTypeName(method)); const paramProps = method.params?.properties || {}; const requiredParams = new Set(method.params?.required || []); @@ -1083,16 +1085,12 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc if (method.stability === "experimental" && !groupExperimental) { lines.push(`// Experimental: ${methodName} is an experimental API and may change or be removed in future versions.`); } - - const returnType = hasResult ? `(*${resultType}, error)` : `error`; const sig = hasParams - ? `func (a *${receiver}) ${methodName}(ctx context.Context, params *${paramsType}) ${returnType}` - : `func (a *${receiver}) ${methodName}(ctx context.Context) ${returnType}`; + ? `func (a *${receiver}) ${methodName}(ctx context.Context, params *${paramsType}) (*${resultType}, error)` + : `func (a *${receiver}) ${methodName}(ctx context.Context) (*${resultType}, error)`; lines.push(sig + ` {`); - const errReturn = hasResult ? `return nil, err` : `return err`; - if (isSession) { lines.push(`\treq := map[string]any{"sessionId": ${sessionIDRef}}`); if (hasParams) { @@ -1118,18 +1116,13 @@ function emitMethod(lines: string[], receiver: string, name: string, method: Rpc } lines.push(`\tif err != nil {`); - lines.push(`\t\t${errReturn}`); + lines.push(`\t\treturn nil, err`); lines.push(`\t}`); - - if (hasResult) { - lines.push(`\tvar result ${resultType}`); - lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil {`); - lines.push(`\t\treturn nil, err`); - lines.push(`\t}`); - lines.push(`\treturn &result, nil`); - } else { - lines.push(`\treturn nil`); - } + lines.push(`\tvar result ${resultType}`); + lines.push(`\tif err := json.Unmarshal(raw, &result); err != nil {`); + lines.push(`\t\treturn nil, err`); + lines.push(`\t}`); + lines.push(`\treturn &result, nil`); lines.push(`}`); lines.push(``); } @@ -1177,12 +1170,8 @@ function emitClientSessionApiRegistration(lines: string[], clientSchema: Record< lines.push(`\t// Experimental: ${clientHandlerMethodName(method.rpcMethod)} is an experimental API and may change or be removed in future versions.`); } const paramsType = resolveType(goParamsTypeName(method)); - if (method.result) { - const resultType = resolveType(goResultTypeName(method)); - lines.push(`\t${clientHandlerMethodName(method.rpcMethod)}(request *${paramsType}) (*${resultType}, error)`); - } else { - lines.push(`\t${clientHandlerMethodName(method.rpcMethod)}(request *${paramsType}) error`); - } + const resultType = resolveType(goResultTypeName(method)); + lines.push(`\t${clientHandlerMethodName(method.rpcMethod)}(request *${paramsType}) (*${resultType}, error)`); } lines.push(`}`); lines.push(``); @@ -1223,22 +1212,15 @@ function emitClientSessionApiRegistration(lines: string[], clientSchema: Record< lines.push(`\t\tif handlers == nil || handlers.${handlerField} == nil {`); lines.push(`\t\t\treturn nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("No ${groupName} handler registered for session: %s", request.SessionID)}`); lines.push(`\t\t}`); - if (method.result) { - lines.push(`\t\tresult, err := handlers.${handlerField}.${clientHandlerMethodName(method.rpcMethod)}(&request)`); - lines.push(`\t\tif err != nil {`); - lines.push(`\t\t\treturn nil, clientSessionHandlerError(err)`); - lines.push(`\t\t}`); - lines.push(`\t\traw, err := json.Marshal(result)`); - lines.push(`\t\tif err != nil {`); - lines.push(`\t\t\treturn nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)}`); - lines.push(`\t\t}`); - lines.push(`\t\treturn raw, nil`); - } else { - lines.push(`\t\tif err := handlers.${handlerField}.${clientHandlerMethodName(method.rpcMethod)}(&request); err != nil {`); - lines.push(`\t\t\treturn nil, clientSessionHandlerError(err)`); - lines.push(`\t\t}`); - lines.push(`\t\treturn json.RawMessage("null"), nil`); - } + lines.push(`\t\tresult, err := handlers.${handlerField}.${clientHandlerMethodName(method.rpcMethod)}(&request)`); + lines.push(`\t\tif err != nil {`); + lines.push(`\t\t\treturn nil, clientSessionHandlerError(err)`); + lines.push(`\t\t}`); + lines.push(`\t\traw, err := json.Marshal(result)`); + lines.push(`\t\tif err != nil {`); + lines.push(`\t\t\treturn nil, &jsonrpc2.Error{Code: -32603, Message: fmt.Sprintf("Failed to marshal response: %v", err)}`); + lines.push(`\t\t}`); + lines.push(`\t\treturn raw, nil`); lines.push(`\t})`); } } From 69225921b1e60862e64f9d5d967ad49c08744982 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 12:18:39 +0100 Subject: [PATCH 04/18] Regenerate now "session.mode.set" returns void Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 4 ++-- go/rpc/generated_rpc.go | 7 +++++-- nodejs/src/generated/rpc.ts | 3 +-- python/copilot/generated/rpc.py | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 800d70d25..66285ed4b 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -2215,10 +2215,10 @@ public async Task GetAsync(CancellationToken cancellationToken = de } /// Calls "session.mode.set". - public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken = default) + public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken = default) { var request = new ModeSetRequest { SessionId = _sessionId, Mode = mode }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.set", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.mode.set", [request], cancellationToken); } } diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 21756a2a4..cebabf865 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -323,6 +323,9 @@ type ModelCapabilitiesOverrideSupports struct { Vision *bool `json:"vision,omitempty"` } +type SessionModeSetResult struct { +} + type ModeSetRequest struct { Mode SessionMode `json:"mode"` } @@ -1376,7 +1379,7 @@ func (a *ModeApi) Get(ctx context.Context) (*SessionMode, error) { return &result, nil } -func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionMode, error) { +func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionModeSetResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["mode"] = params.Mode @@ -1385,7 +1388,7 @@ func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionMode if err != nil { return nil, err } - var result SessionMode + var result SessionModeSetResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index b6d356e7b..07e4c7062 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -536,7 +536,6 @@ export interface SessionModeGetRequest { sessionId: string; } - export interface ModeSetRequest { /** * Target session identifier @@ -1850,7 +1849,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin mode: { get: async (): Promise => connection.sendRequest("session.mode.get", { sessionId }), - set: async (params: Omit): Promise => + set: async (params: Omit): Promise => connection.sendRequest("session.mode.set", { sessionId, ...params }), }, plan: { diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 41041708c..3dbae090b 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -3860,10 +3860,10 @@ def __init__(self, client: "JsonRpcClient", session_id: str): async def get(self, *, timeout: float | None = None) -> SessionMode: return SessionMode(await self._client.request("session.mode.get", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def set(self, params: ModeSetRequest, *, timeout: float | None = None) -> SessionMode: + async def set(self, params: ModeSetRequest, *, timeout: float | None = None) -> None: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SessionMode(await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout)) class PlanApi: From 222851ef46e0b3d9dfb78d2c759f420e59e4d3d5 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 12:52:31 +0100 Subject: [PATCH 05/18] Fully support void-returning RPC methods and regenerate Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 161 +++++------------ go/rpc/generated_rpc.go | 26 +-- nodejs/src/generated/rpc.ts | 83 +++------ python/copilot/generated/rpc.py | 297 +++++--------------------------- scripts/codegen/csharp.ts | 31 ++-- scripts/codegen/go.ts | 7 +- scripts/codegen/python.ts | 9 +- scripts/codegen/typescript.ts | 7 +- scripts/codegen/utils.ts | 10 ++ 9 files changed, 159 insertions(+), 472 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 66285ed4b..9dcd3c36b 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -517,11 +517,6 @@ internal class SessionPlanReadRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for PlanUpdate operations. -public class PlanUpdateResult -{ -} - /// RPC data type for PlanUpdate operations. internal class PlanUpdateRequest { @@ -534,11 +529,6 @@ internal class PlanUpdateRequest public string Content { get; set; } = string.Empty; } -/// RPC data type for PlanDelete operations. -public class PlanDelete -{ -} - /// RPC data type for SessionPlanDelete operations. internal class SessionPlanDeleteRequest { @@ -583,11 +573,6 @@ internal class WorkspaceReadFileRequest public string Path { get; set; } = string.Empty; } -/// RPC data type for WorkspaceCreateFile operations. -public class WorkspaceCreateFileResult -{ -} - /// RPC data type for WorkspaceCreateFile operations. internal class WorkspaceCreateFileRequest { @@ -732,14 +717,7 @@ internal class AgentSelectRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for AgentDeselect operations. -[Experimental(Diagnostics.Experimental)] -public class AgentDeselect -{ -} - /// RPC data type for SessionAgentDeselect operations. -[Experimental(Diagnostics.Experimental)] internal class SessionAgentDeselectRequest { /// Target session identifier. @@ -827,12 +805,6 @@ internal class SessionSkillsListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SkillsEnable operations. -[Experimental(Diagnostics.Experimental)] -public class SkillsEnableResult -{ -} - /// RPC data type for SkillsEnable operations. [Experimental(Diagnostics.Experimental)] internal class SkillsEnableRequest @@ -846,12 +818,6 @@ internal class SkillsEnableRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for SkillsDisable operations. -[Experimental(Diagnostics.Experimental)] -public class SkillsDisableResult -{ -} - /// RPC data type for SkillsDisable operations. [Experimental(Diagnostics.Experimental)] internal class SkillsDisableRequest @@ -865,14 +831,7 @@ internal class SkillsDisableRequest public string Name { get; set; } = string.Empty; } -/// RPC data type for SkillsReload operations. -[Experimental(Diagnostics.Experimental)] -public class SkillsReload -{ -} - /// RPC data type for SessionSkillsReload operations. -[Experimental(Diagnostics.Experimental)] internal class SessionSkillsReloadRequest { /// Target session identifier. @@ -919,12 +878,6 @@ internal class SessionMcpListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for McpEnable operations. -[Experimental(Diagnostics.Experimental)] -public class McpEnableResult -{ -} - /// RPC data type for McpEnable operations. [Experimental(Diagnostics.Experimental)] internal class McpEnableRequest @@ -939,12 +892,6 @@ internal class McpEnableRequest public string ServerName { get; set; } = string.Empty; } -/// RPC data type for McpDisable operations. -[Experimental(Diagnostics.Experimental)] -public class McpDisableResult -{ -} - /// RPC data type for McpDisable operations. [Experimental(Diagnostics.Experimental)] internal class McpDisableRequest @@ -959,14 +906,7 @@ internal class McpDisableRequest public string ServerName { get; set; } = string.Empty; } -/// RPC data type for McpReload operations. -[Experimental(Diagnostics.Experimental)] -public class McpReload -{ -} - /// RPC data type for SessionMcpReload operations. -[Experimental(Diagnostics.Experimental)] internal class SessionMcpReloadRequest { /// Target session identifier. @@ -1054,12 +994,6 @@ internal class SessionExtensionsListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for ExtensionsEnable operations. -[Experimental(Diagnostics.Experimental)] -public class ExtensionsEnableResult -{ -} - /// RPC data type for ExtensionsEnable operations. [Experimental(Diagnostics.Experimental)] internal class ExtensionsEnableRequest @@ -1073,12 +1007,6 @@ internal class ExtensionsEnableRequest public string Id { get; set; } = string.Empty; } -/// RPC data type for ExtensionsDisable operations. -[Experimental(Diagnostics.Experimental)] -public class ExtensionsDisableResult -{ -} - /// RPC data type for ExtensionsDisable operations. [Experimental(Diagnostics.Experimental)] internal class ExtensionsDisableRequest @@ -1092,14 +1020,7 @@ internal class ExtensionsDisableRequest public string Id { get; set; } = string.Empty; } -/// RPC data type for ExtensionsReload operations. -[Experimental(Diagnostics.Experimental)] -public class ExtensionsReload -{ -} - /// RPC data type for SessionExtensionsReload operations. -[Experimental(Diagnostics.Experimental)] internal class SessionExtensionsReloadRequest { /// Target session identifier. @@ -2242,17 +2163,17 @@ public async Task ReadAsync(CancellationToken cancellationToken = default) } /// Calls "session.plan.update". - public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) + public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) { var request = new PlanUpdateRequest { SessionId = _sessionId, Content = content }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.update", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.update", [request], cancellationToken); } /// Calls "session.plan.delete". - public async Task DeleteAsync(CancellationToken cancellationToken = default) + public async Task DeleteAsync(CancellationToken cancellationToken = default) { var request = new SessionPlanDeleteRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.delete", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.delete", [request], cancellationToken); } } @@ -2283,10 +2204,10 @@ public async Task ReadFileAsync(string path, Cancellati } /// Calls "session.workspace.createFile". - public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) + public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) { var request = new WorkspaceCreateFileRequest { SessionId = _sessionId, Path = path, Content = content }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.createFile", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.createFile", [request], cancellationToken); } } @@ -2312,7 +2233,6 @@ public async Task StartAsync(string? prompt = null, Cancellati } /// Provides session-scoped Agent APIs. -[Experimental(Diagnostics.Experimental)] public class AgentApi { private readonly JsonRpc _rpc; @@ -2325,6 +2245,7 @@ internal AgentApi(JsonRpc rpc, string sessionId) } /// Calls "session.agent.list". + [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentListRequest { SessionId = _sessionId }; @@ -2332,6 +2253,7 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Calls "session.agent.getCurrent". + [Experimental(Diagnostics.Experimental)] public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentGetCurrentRequest { SessionId = _sessionId }; @@ -2339,6 +2261,7 @@ public async Task GetCurrentAsync(CancellationToken cancellationTo } /// Calls "session.agent.select". + [Experimental(Diagnostics.Experimental)] public async Task SelectAsync(string name, CancellationToken cancellationToken = default) { var request = new AgentSelectRequest { SessionId = _sessionId, Name = name }; @@ -2346,13 +2269,14 @@ public async Task SelectAsync(string name, CancellationToken } /// Calls "session.agent.deselect". - public async Task DeselectAsync(CancellationToken cancellationToken = default) + public async Task DeselectAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentDeselectRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.deselect", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.deselect", [request], cancellationToken); } /// Calls "session.agent.reload". + [Experimental(Diagnostics.Experimental)] public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentReloadRequest { SessionId = _sessionId }; @@ -2361,7 +2285,6 @@ public async Task ReloadAsync(CancellationToken cancellationToken = } /// Provides session-scoped Skills APIs. -[Experimental(Diagnostics.Experimental)] public class SkillsApi { private readonly JsonRpc _rpc; @@ -2374,6 +2297,7 @@ internal SkillsApi(JsonRpc rpc, string sessionId) } /// Calls "session.skills.list". + [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionSkillsListRequest { SessionId = _sessionId }; @@ -2381,29 +2305,30 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Calls "session.skills.enable". - public async Task EnableAsync(string name, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task EnableAsync(string name, CancellationToken cancellationToken = default) { var request = new SkillsEnableRequest { SessionId = _sessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.enable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.enable", [request], cancellationToken); } /// Calls "session.skills.disable". - public async Task DisableAsync(string name, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task DisableAsync(string name, CancellationToken cancellationToken = default) { var request = new SkillsDisableRequest { SessionId = _sessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.disable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.disable", [request], cancellationToken); } /// Calls "session.skills.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionSkillsReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.reload", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.skills.reload", [request], cancellationToken); } } /// Provides session-scoped Mcp APIs. -[Experimental(Diagnostics.Experimental)] public class McpApi { private readonly JsonRpc _rpc; @@ -2416,6 +2341,7 @@ internal McpApi(JsonRpc rpc, string sessionId) } /// Calls "session.mcp.list". + [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpListRequest { SessionId = _sessionId }; @@ -2423,24 +2349,26 @@ public async Task ListAsync(CancellationToken cancellationToken = defau } /// Calls "session.mcp.enable". - public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) { var request = new McpEnableRequest { SessionId = _sessionId, ServerName = serverName }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.enable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.enable", [request], cancellationToken); } /// Calls "session.mcp.disable". - public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) { var request = new McpDisableRequest { SessionId = _sessionId, ServerName = serverName }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.disable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.disable", [request], cancellationToken); } /// Calls "session.mcp.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.reload", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.reload", [request], cancellationToken); } } @@ -2466,7 +2394,6 @@ public async Task ListAsync(CancellationToken cancellationToken = de } /// Provides session-scoped Extensions APIs. -[Experimental(Diagnostics.Experimental)] public class ExtensionsApi { private readonly JsonRpc _rpc; @@ -2479,6 +2406,7 @@ internal ExtensionsApi(JsonRpc rpc, string sessionId) } /// Calls "session.extensions.list". + [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionExtensionsListRequest { SessionId = _sessionId }; @@ -2486,24 +2414,26 @@ public async Task ListAsync(CancellationToken cancellationToken = } /// Calls "session.extensions.enable". - public async Task EnableAsync(string id, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task EnableAsync(string id, CancellationToken cancellationToken = default) { var request = new ExtensionsEnableRequest { SessionId = _sessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.enable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.enable", [request], cancellationToken); } /// Calls "session.extensions.disable". - public async Task DisableAsync(string id, CancellationToken cancellationToken = default) + [Experimental(Diagnostics.Experimental)] + public async Task DisableAsync(string id, CancellationToken cancellationToken = default) { var request = new ExtensionsDisableRequest { SessionId = _sessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.disable", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.disable", [request], cancellationToken); } /// Calls "session.extensions.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionExtensionsReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.reload", [request], cancellationToken); + await CopilotClient.InvokeRpcAsync(_rpc, "session.extensions.reload", [request], cancellationToken); } } @@ -2824,7 +2754,6 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func => connection.sendRequest("session.plan.read", { sessionId }), - update: async (params: Omit): Promise => + update: async (params: Omit): Promise => connection.sendRequest("session.plan.update", { sessionId, ...params }), - delete: async (): Promise => + delete: async (): Promise => connection.sendRequest("session.plan.delete", { sessionId }), }, workspace: { @@ -1865,7 +1825,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.workspace.listFiles", { sessionId }), readFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }), - createFile: async (params: Omit): Promise => + createFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.createFile", { sessionId, ...params }), }, /** @experimental */ @@ -1873,39 +1833,46 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin start: async (params: Omit): Promise => connection.sendRequest("session.fleet.start", { sessionId, ...params }), }, - /** @experimental */ agent: { + /** @experimental */ list: async (): Promise => connection.sendRequest("session.agent.list", { sessionId }), + /** @experimental */ getCurrent: async (): Promise => connection.sendRequest("session.agent.getCurrent", { sessionId }), + /** @experimental */ select: async (params: Omit): Promise => connection.sendRequest("session.agent.select", { sessionId, ...params }), - deselect: async (): Promise => + deselect: async (): Promise => connection.sendRequest("session.agent.deselect", { sessionId }), + /** @experimental */ reload: async (): Promise => connection.sendRequest("session.agent.reload", { sessionId }), }, - /** @experimental */ skills: { + /** @experimental */ list: async (): Promise => connection.sendRequest("session.skills.list", { sessionId }), - enable: async (params: Omit): Promise => + /** @experimental */ + enable: async (params: Omit): Promise => connection.sendRequest("session.skills.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + /** @experimental */ + disable: async (params: Omit): Promise => connection.sendRequest("session.skills.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.skills.reload", { sessionId }), }, - /** @experimental */ mcp: { + /** @experimental */ list: async (): Promise => connection.sendRequest("session.mcp.list", { sessionId }), - enable: async (params: Omit): Promise => + /** @experimental */ + enable: async (params: Omit): Promise => connection.sendRequest("session.mcp.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + /** @experimental */ + disable: async (params: Omit): Promise => connection.sendRequest("session.mcp.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.mcp.reload", { sessionId }), }, /** @experimental */ @@ -1913,15 +1880,17 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin list: async (): Promise => connection.sendRequest("session.plugins.list", { sessionId }), }, - /** @experimental */ extensions: { + /** @experimental */ list: async (): Promise => connection.sendRequest("session.extensions.list", { sessionId }), - enable: async (params: Omit): Promise => + /** @experimental */ + enable: async (params: Omit): Promise => connection.sendRequest("session.extensions.enable", { sessionId, ...params }), - disable: async (params: Omit): Promise => + /** @experimental */ + disable: async (params: Omit): Promise => connection.sendRequest("session.extensions.disable", { sessionId, ...params }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.extensions.reload", { sessionId }), }, tools: { diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 3dbae090b..ddad580e3 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -1131,17 +1131,6 @@ def to_dict(self) -> dict: result["path"] = from_union([from_none, from_str], self.path) return result -@dataclass -class PlanUpdateResult: - @staticmethod - def from_dict(obj: Any) -> 'PlanUpdateResult': - assert isinstance(obj, dict) - return PlanUpdateResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class PlanUpdateRequest: content: str @@ -1158,17 +1147,6 @@ def to_dict(self) -> dict: result["content"] = from_str(self.content) return result -@dataclass -class PlanDelete: - @staticmethod - def from_dict(obj: Any) -> 'PlanDelete': - assert isinstance(obj, dict) - return PlanDelete() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class WorkspaceFiles: files: list[str] @@ -1217,17 +1195,6 @@ def to_dict(self) -> dict: result["path"] = from_str(self.path) return result -@dataclass -class WorkspaceCreateFileResult: - @staticmethod - def from_dict(obj: Any) -> 'WorkspaceCreateFileResult': - assert isinstance(obj, dict) - return WorkspaceCreateFileResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class WorkspaceCreateFileRequest: content: str @@ -1431,18 +1398,6 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class AgentDeselect: - @staticmethod - def from_dict(obj: Any) -> 'AgentDeselect': - assert isinstance(obj, dict) - return AgentDeselect() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class AgentReloadAgent: description: str @@ -1545,18 +1500,6 @@ def to_dict(self) -> dict: result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class SkillsEnableResult: - @staticmethod - def from_dict(obj: Any) -> 'SkillsEnableResult': - assert isinstance(obj, dict) - return SkillsEnableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SkillsEnableRequest: @@ -1574,18 +1517,6 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class SkillsDisableResult: - @staticmethod - def from_dict(obj: Any) -> 'SkillsDisableResult': - assert isinstance(obj, dict) - return SkillsDisableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class SkillsDisableRequest: @@ -1603,18 +1534,6 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class SkillsReload: - @staticmethod - def from_dict(obj: Any) -> 'SkillsReload': - assert isinstance(obj, dict) - return SkillsReload() - - def to_dict(self) -> dict: - result: dict = {} - return result - class MCPServerStatus(Enum): """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" @@ -1671,17 +1590,6 @@ def to_dict(self) -> dict: result["servers"] = from_list(lambda x: to_class(MCPServer, x), self.servers) return result -@dataclass -class MCPEnableResult: - @staticmethod - def from_dict(obj: Any) -> 'MCPEnableResult': - assert isinstance(obj, dict) - return MCPEnableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class MCPEnableRequest: server_name: str @@ -1698,17 +1606,6 @@ def to_dict(self) -> dict: result["serverName"] = from_str(self.server_name) return result -@dataclass -class MCPDisableResult: - @staticmethod - def from_dict(obj: Any) -> 'MCPDisableResult': - assert isinstance(obj, dict) - return MCPDisableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class MCPDisableRequest: server_name: str @@ -1725,17 +1622,6 @@ def to_dict(self) -> dict: result["serverName"] = from_str(self.server_name) return result -@dataclass -class MCPReload: - @staticmethod - def from_dict(obj: Any) -> 'MCPReload': - assert isinstance(obj, dict) - return MCPReload() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class Plugin: enabled: bool @@ -1849,18 +1735,6 @@ def to_dict(self) -> dict: result["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class ExtensionsEnableResult: - @staticmethod - def from_dict(obj: Any) -> 'ExtensionsEnableResult': - assert isinstance(obj, dict) - return ExtensionsEnableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class ExtensionsEnableRequest: @@ -1878,18 +1752,6 @@ def to_dict(self) -> dict: result["id"] = from_str(self.id) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class ExtensionsDisableResult: - @staticmethod - def from_dict(obj: Any) -> 'ExtensionsDisableResult': - assert isinstance(obj, dict) - return ExtensionsDisableResult() - - def to_dict(self) -> dict: - result: dict = {} - return result - # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class ExtensionsDisableRequest: @@ -1907,18 +1769,6 @@ def to_dict(self) -> dict: result["id"] = from_str(self.id) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class ExtensionsReload: - @staticmethod - def from_dict(obj: Any) -> 'ExtensionsReload': - assert isinstance(obj, dict) - return ExtensionsReload() - - def to_dict(self) -> dict: - result: dict = {} - return result - @dataclass class HandleToolCallResult: success: bool @@ -3341,24 +3191,12 @@ def plan_from_dict(s: Any) -> Plan: def plan_to_dict(x: Plan) -> Any: return to_class(Plan, x) -def plan_update_result_from_dict(s: Any) -> PlanUpdateResult: - return PlanUpdateResult.from_dict(s) - -def plan_update_result_to_dict(x: PlanUpdateResult) -> Any: - return to_class(PlanUpdateResult, x) - def plan_update_request_from_dict(s: Any) -> PlanUpdateRequest: return PlanUpdateRequest.from_dict(s) def plan_update_request_to_dict(x: PlanUpdateRequest) -> Any: return to_class(PlanUpdateRequest, x) -def plan_delete_from_dict(s: Any) -> PlanDelete: - return PlanDelete.from_dict(s) - -def plan_delete_to_dict(x: PlanDelete) -> Any: - return to_class(PlanDelete, x) - def workspace_files_from_dict(s: Any) -> WorkspaceFiles: return WorkspaceFiles.from_dict(s) @@ -3377,12 +3215,6 @@ def workspace_read_file_request_from_dict(s: Any) -> WorkspaceReadFileRequest: def workspace_read_file_request_to_dict(x: WorkspaceReadFileRequest) -> Any: return to_class(WorkspaceReadFileRequest, x) -def workspace_create_file_result_from_dict(s: Any) -> WorkspaceCreateFileResult: - return WorkspaceCreateFileResult.from_dict(s) - -def workspace_create_file_result_to_dict(x: WorkspaceCreateFileResult) -> Any: - return to_class(WorkspaceCreateFileResult, x) - def workspace_create_file_request_from_dict(s: Any) -> WorkspaceCreateFileRequest: return WorkspaceCreateFileRequest.from_dict(s) @@ -3425,12 +3257,6 @@ def agent_select_request_from_dict(s: Any) -> AgentSelectRequest: def agent_select_request_to_dict(x: AgentSelectRequest) -> Any: return to_class(AgentSelectRequest, x) -def agent_deselect_from_dict(s: Any) -> AgentDeselect: - return AgentDeselect.from_dict(s) - -def agent_deselect_to_dict(x: AgentDeselect) -> Any: - return to_class(AgentDeselect, x) - def agent_reload_from_dict(s: Any) -> AgentReload: return AgentReload.from_dict(s) @@ -3443,72 +3269,36 @@ def skill_list_from_dict(s: Any) -> SkillList: def skill_list_to_dict(x: SkillList) -> Any: return to_class(SkillList, x) -def skills_enable_result_from_dict(s: Any) -> SkillsEnableResult: - return SkillsEnableResult.from_dict(s) - -def skills_enable_result_to_dict(x: SkillsEnableResult) -> Any: - return to_class(SkillsEnableResult, x) - def skills_enable_request_from_dict(s: Any) -> SkillsEnableRequest: return SkillsEnableRequest.from_dict(s) def skills_enable_request_to_dict(x: SkillsEnableRequest) -> Any: return to_class(SkillsEnableRequest, x) -def skills_disable_result_from_dict(s: Any) -> SkillsDisableResult: - return SkillsDisableResult.from_dict(s) - -def skills_disable_result_to_dict(x: SkillsDisableResult) -> Any: - return to_class(SkillsDisableResult, x) - def skills_disable_request_from_dict(s: Any) -> SkillsDisableRequest: return SkillsDisableRequest.from_dict(s) def skills_disable_request_to_dict(x: SkillsDisableRequest) -> Any: return to_class(SkillsDisableRequest, x) -def skills_reload_from_dict(s: Any) -> SkillsReload: - return SkillsReload.from_dict(s) - -def skills_reload_to_dict(x: SkillsReload) -> Any: - return to_class(SkillsReload, x) - def mcp_list_from_dict(s: Any) -> MCPList: return MCPList.from_dict(s) def mcp_list_to_dict(x: MCPList) -> Any: return to_class(MCPList, x) -def mcp_enable_result_from_dict(s: Any) -> MCPEnableResult: - return MCPEnableResult.from_dict(s) - -def mcp_enable_result_to_dict(x: MCPEnableResult) -> Any: - return to_class(MCPEnableResult, x) - def mcp_enable_request_from_dict(s: Any) -> MCPEnableRequest: return MCPEnableRequest.from_dict(s) def mcp_enable_request_to_dict(x: MCPEnableRequest) -> Any: return to_class(MCPEnableRequest, x) -def mcp_disable_result_from_dict(s: Any) -> MCPDisableResult: - return MCPDisableResult.from_dict(s) - -def mcp_disable_result_to_dict(x: MCPDisableResult) -> Any: - return to_class(MCPDisableResult, x) - def mcp_disable_request_from_dict(s: Any) -> MCPDisableRequest: return MCPDisableRequest.from_dict(s) def mcp_disable_request_to_dict(x: MCPDisableRequest) -> Any: return to_class(MCPDisableRequest, x) -def mcp_reload_from_dict(s: Any) -> MCPReload: - return MCPReload.from_dict(s) - -def mcp_reload_to_dict(x: MCPReload) -> Any: - return to_class(MCPReload, x) - def plugin_list_from_dict(s: Any) -> PluginList: return PluginList.from_dict(s) @@ -3521,36 +3311,18 @@ def extension_list_from_dict(s: Any) -> ExtensionList: def extension_list_to_dict(x: ExtensionList) -> Any: return to_class(ExtensionList, x) -def extensions_enable_result_from_dict(s: Any) -> ExtensionsEnableResult: - return ExtensionsEnableResult.from_dict(s) - -def extensions_enable_result_to_dict(x: ExtensionsEnableResult) -> Any: - return to_class(ExtensionsEnableResult, x) - def extensions_enable_request_from_dict(s: Any) -> ExtensionsEnableRequest: return ExtensionsEnableRequest.from_dict(s) def extensions_enable_request_to_dict(x: ExtensionsEnableRequest) -> Any: return to_class(ExtensionsEnableRequest, x) -def extensions_disable_result_from_dict(s: Any) -> ExtensionsDisableResult: - return ExtensionsDisableResult.from_dict(s) - -def extensions_disable_result_to_dict(x: ExtensionsDisableResult) -> Any: - return to_class(ExtensionsDisableResult, x) - def extensions_disable_request_from_dict(s: Any) -> ExtensionsDisableRequest: return ExtensionsDisableRequest.from_dict(s) def extensions_disable_request_to_dict(x: ExtensionsDisableRequest) -> Any: return to_class(ExtensionsDisableRequest, x) -def extensions_reload_from_dict(s: Any) -> ExtensionsReload: - return ExtensionsReload.from_dict(s) - -def extensions_reload_to_dict(x: ExtensionsReload) -> Any: - return to_class(ExtensionsReload, x) - def handle_tool_call_result_from_dict(s: Any) -> HandleToolCallResult: return HandleToolCallResult.from_dict(s) @@ -3874,13 +3646,13 @@ def __init__(self, client: "JsonRpcClient", session_id: str): async def read(self, *, timeout: float | None = None) -> Plan: return Plan.from_dict(await self._client.request("session.plan.read", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def update(self, params: PlanUpdateRequest, *, timeout: float | None = None) -> PlanUpdateResult: + async def update(self, params: PlanUpdateRequest, *, timeout: float | None = None) -> None: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return PlanUpdateResult.from_dict(await self._client.request("session.plan.update", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.plan.update", params_dict, **_timeout_kwargs(timeout)) - async def delete(self, *, timeout: float | None = None) -> PlanDelete: - return PlanDelete.from_dict(await self._client.request("session.plan.delete", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def delete(self, *, timeout: float | None = None) -> None: + await self._client.request("session.plan.delete", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) class WorkspaceApi: @@ -3896,10 +3668,10 @@ async def read_file(self, params: WorkspaceReadFileRequest, *, timeout: float | params_dict["sessionId"] = self._session_id return WorkspaceReadFileResult.from_dict(await self._client.request("session.workspace.readFile", params_dict, **_timeout_kwargs(timeout))) - async def create_file(self, params: WorkspaceCreateFileRequest, *, timeout: float | None = None) -> WorkspaceCreateFileResult: + async def create_file(self, params: WorkspaceCreateFileRequest, *, timeout: float | None = None) -> None: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return WorkspaceCreateFileResult.from_dict(await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.workspace.createFile", params_dict, **_timeout_kwargs(timeout)) # Experimental: this API group is experimental and may change or be removed. @@ -3914,74 +3686,81 @@ async def start(self, params: FleetStartRequest, *, timeout: float | None = None return FleetStartResult.from_dict(await self._client.request("session.fleet.start", params_dict, **_timeout_kwargs(timeout))) -# Experimental: this API group is experimental and may change or be removed. class AgentApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> AgentList: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentList.from_dict(await self._client.request("session.agent.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def get_current(self, *, timeout: float | None = None) -> AgentCurrent: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentCurrent.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def select(self, params: AgentSelectRequest, *, timeout: float | None = None) -> AgentSelectResult: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return AgentSelectResult.from_dict(await self._client.request("session.agent.select", params_dict, **_timeout_kwargs(timeout))) - async def deselect(self, *, timeout: float | None = None) -> AgentDeselect: - return AgentDeselect.from_dict(await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def deselect(self, *, timeout: float | None = None) -> None: + await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) async def reload(self, *, timeout: float | None = None) -> AgentReload: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentReload.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) -# Experimental: this API group is experimental and may change or be removed. class SkillsApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> SkillList: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return SkillList.from_dict(await self._client.request("session.skills.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: SkillsEnableRequest, *, timeout: float | None = None) -> SkillsEnableResult: + async def enable(self, params: SkillsEnableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SkillsEnableResult.from_dict(await self._client.request("session.skills.enable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.skills.enable", params_dict, **_timeout_kwargs(timeout)) - async def disable(self, params: SkillsDisableRequest, *, timeout: float | None = None) -> SkillsDisableResult: + async def disable(self, params: SkillsDisableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return SkillsDisableResult.from_dict(await self._client.request("session.skills.disable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.skills.disable", params_dict, **_timeout_kwargs(timeout)) - async def reload(self, *, timeout: float | None = None) -> SkillsReload: - return SkillsReload.from_dict(await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> None: + await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) -# Experimental: this API group is experimental and may change or be removed. class McpApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> MCPList: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return MCPList.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: MCPEnableRequest, *, timeout: float | None = None) -> MCPEnableResult: + async def enable(self, params: MCPEnableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return MCPEnableResult.from_dict(await self._client.request("session.mcp.enable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.mcp.enable", params_dict, **_timeout_kwargs(timeout)) - async def disable(self, params: MCPDisableRequest, *, timeout: float | None = None) -> MCPDisableResult: + async def disable(self, params: MCPDisableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return MCPDisableResult.from_dict(await self._client.request("session.mcp.disable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.mcp.disable", params_dict, **_timeout_kwargs(timeout)) - async def reload(self, *, timeout: float | None = None) -> MCPReload: - return MCPReload.from_dict(await self._client.request("session.mcp.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> None: + await self._client.request("session.mcp.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) # Experimental: this API group is experimental and may change or be removed. @@ -3994,27 +3773,29 @@ async def list(self, *, timeout: float | None = None) -> PluginList: return PluginList.from_dict(await self._client.request("session.plugins.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) -# Experimental: this API group is experimental and may change or be removed. class ExtensionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> ExtensionList: + """.. warning:: This API is experimental and may change or be removed in future versions.""" return ExtensionList.from_dict(await self._client.request("session.extensions.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def enable(self, params: ExtensionsEnableRequest, *, timeout: float | None = None) -> ExtensionsEnableResult: + async def enable(self, params: ExtensionsEnableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return ExtensionsEnableResult.from_dict(await self._client.request("session.extensions.enable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.extensions.enable", params_dict, **_timeout_kwargs(timeout)) - async def disable(self, params: ExtensionsDisableRequest, *, timeout: float | None = None) -> ExtensionsDisableResult: + async def disable(self, params: ExtensionsDisableRequest, *, timeout: float | None = None) -> None: + """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id - return ExtensionsDisableResult.from_dict(await self._client.request("session.extensions.disable", params_dict, **_timeout_kwargs(timeout))) + await self._client.request("session.extensions.disable", params_dict, **_timeout_kwargs(timeout)) - async def reload(self, *, timeout: float | None = None) -> ExtensionsReload: - return ExtensionsReload.from_dict(await self._client.request("session.extensions.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> None: + await self._client.request("session.extensions.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) class ToolsApi: diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 566ba8df0..5cd86b046 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -18,6 +18,7 @@ import { getSessionEventsSchemaPath, isNodeFullyExperimental, isObjectSchema, + isVoidSchema, isRpcMethod, REPO_ROOT, writeGeneratedFile, @@ -952,14 +953,14 @@ function emitServerInstanceMethod( groupExperimental: boolean ): void { const methodName = toPascalCase(name); - let resultClassName = method.result ? resultTypeName(method) : ""; - if (method.result && method.stability === "experimental") { + let resultClassName = !isVoidSchema(method.result) ? resultTypeName(method) : ""; + if (!isVoidSchema(method.result) && method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } if (isObjectSchema(method.result)) { const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); if (resultClass) classes.push(resultClass); - } else if (method.result) { + } else if (!isVoidSchema(method.result)) { resultClassName = emitNonObjectResultType(resultClassName, method.result, classes); } @@ -1003,18 +1004,18 @@ function emitServerInstanceMethod( } sigParams.push("CancellationToken cancellationToken = default"); - const taskType = method.result ? `Task<${resultClassName}>` : "Task"; + const taskType = !isVoidSchema(method.result) ? `Task<${resultClassName}>` : "Task"; lines.push(`${indent}public async ${taskType} ${methodName}Async(${sigParams.join(", ")})`); lines.push(`${indent}{`); if (requestClassName && bodyAssignments.length > 0) { lines.push(`${indent} var request = new ${requestClassName} { ${bodyAssignments.join(", ")} };`); - if (method.result) { + if (!isVoidSchema(method.result)) { lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`); } else { lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [request], cancellationToken);`); } } else { - if (method.result) { + if (!isVoidSchema(method.result)) { lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [], cancellationToken);`); } else { lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [], cancellationToken);`); @@ -1052,14 +1053,14 @@ function emitSessionRpcClasses(node: Record, classes: string[]) function emitSessionMethod(key: string, method: RpcMethod, lines: string[], classes: string[], indent: string, groupExperimental: boolean): void { const methodName = toPascalCase(key); - let resultClassName = method.result ? resultTypeName(method) : ""; - if (method.result && method.stability === "experimental") { + let resultClassName = !isVoidSchema(method.result) ? resultTypeName(method) : ""; + if (!isVoidSchema(method.result) && method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } if (isObjectSchema(method.result)) { const resultClass = emitRpcClass(resultClassName, method.result, "public", classes); if (resultClass) classes.push(resultClass); - } else if (method.result) { + } else if (!isVoidSchema(method.result)) { resultClassName = emitNonObjectResultType(resultClassName, method.result, classes); } @@ -1098,10 +1099,10 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas } sigParams.push("CancellationToken cancellationToken = default"); - const taskType = method.result ? `Task<${resultClassName}>` : "Task"; + const taskType = !isVoidSchema(method.result) ? `Task<${resultClassName}>` : "Task"; lines.push(`${indent}public async ${taskType} ${methodName}Async(${sigParams.join(", ")})`); lines.push(`${indent}{`, `${indent} var request = new ${requestClassName} { ${bodyAssignments.join(", ")} };`); - if (method.result) { + if (!isVoidSchema(method.result)) { lines.push(`${indent} return await CopilotClient.InvokeRpcAsync<${resultClassName}>(_rpc, "${method.rpcMethod}", [request], cancellationToken);`, `${indent}}`); } else { lines.push(`${indent} await CopilotClient.InvokeRpcAsync(_rpc, "${method.rpcMethod}", [request], cancellationToken);`, `${indent}}`); @@ -1152,7 +1153,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, for (const { methods } of groups) { for (const method of methods) { - if (method.result) { + if (!isVoidSchema(method.result)) { if (isObjectSchema(method.result)) { const resultClass = emitRpcClass(resultTypeName(method), method.result, "public", classes); if (resultClass) classes.push(resultClass); @@ -1179,7 +1180,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, lines.push(`{`); for (const method of methods) { const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; - const taskType = method.result ? `Task<${resultTypeName(method)}>` : "Task"; + const taskType = !isVoidSchema(method.result) ? `Task<${resultTypeName(method)}>` : "Task"; lines.push(` /// Handles "${method.rpcMethod}".`); if (method.stability === "experimental" && !groupExperimental) { lines.push(` [Experimental(Diagnostics.Experimental)]`); @@ -1222,7 +1223,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, const handlerMethod = clientHandlerMethodName(method.rpcMethod); const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; const paramsClass = paramsTypeName(method); - const taskType = method.result ? `Task<${resultTypeName(method)}>` : "Task"; + const taskType = !isVoidSchema(method.result) ? `Task<${resultTypeName(method)}>` : "Task"; const registrationVar = `register${typeToClassName(method.rpcMethod)}Method`; if (hasParams) { @@ -1230,7 +1231,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, lines.push(` {`); lines.push(` var handler = getHandlers(request.SessionId).${handlerProperty};`); lines.push(` if (handler is null) throw new InvalidOperationException($"No ${groupName} handler registered for session: {request.SessionId}");`); - if (method.result) { + if (!isVoidSchema(method.result)) { lines.push(` return await handler.${handlerMethod}(request, cancellationToken);`); } else { lines.push(` await handler.${handlerMethod}(request, cancellationToken);`); diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 2e3a55b91..307083b0d 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -18,6 +18,7 @@ import { getSessionEventsSchemaPath, hoistTitledSchemas, isNodeFullyExperimental, + isVoidSchema, isRpcMethod, postProcessSchema, writeGeneratedFile, @@ -864,11 +865,11 @@ async function generateRpc(schemaPath?: string): Promise { }; for (const method of allMethods) { - if (method.result) { - combinedSchema.definitions![goResultTypeName(method)] = method.result; - } else { + if (isVoidSchema(method.result)) { // Emit an empty struct for void results (forward-compatible with adding fields later) combinedSchema.definitions![goResultTypeName(method)] = { type: "object", properties: {}, additionalProperties: false }; + } else { + combinedSchema.definitions![goResultTypeName(method)] = method.result; } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { // For session methods, filter out sessionId from params type diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index ac81b2d3c..7dccfeca9 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -16,6 +16,7 @@ import { getSessionEventsSchemaPath, hoistTitledSchemas, isObjectSchema, + isVoidSchema, isRpcMethod, postProcessSchema, writeGeneratedFile, @@ -285,7 +286,7 @@ async function generateRpc(schemaPath?: string): Promise { }; for (const method of allMethods) { - if (method.result) { + if (!isVoidSchema(method.result)) { combinedSchema.definitions![pythonResultTypeName(method)] = method.result; } if (method.params?.properties && Object.keys(method.params.properties).length > 0) { @@ -474,7 +475,7 @@ function emitRpcWrapper(lines: string[], node: Record, isSessio function emitMethod(lines: string[], name: string, method: RpcMethod, isSession: boolean, resolveType: (name: string) => string, groupExperimental = false): void { const methodName = toSnakeCase(name); - const hasResult = !!method.result; + const hasResult = !isVoidSchema(method.result); const resultType = hasResult ? resolveType(pythonResultTypeName(method)) : "None"; const resultIsObject = isObjectSchema(method.result); @@ -597,7 +598,7 @@ function emitClientSessionHandlerMethod( groupExperimental = false ): void { const paramsType = resolveType(pythonParamsTypeName(method)); - const resultType = method.result ? resolveType(pythonResultTypeName(method)) : "None"; + const resultType = !isVoidSchema(method.result) ? resolveType(pythonResultTypeName(method)) : "None"; lines.push(` async def ${toSnakeCase(name)}(self, params: ${paramsType}) -> ${resultType}:`); if (method.stability === "experimental" && !groupExperimental) { lines.push(` """.. warning:: This API is experimental and may change or be removed in future versions."""`); @@ -614,7 +615,7 @@ function emitClientSessionRegistrationMethod( ): void { const handlerVariableName = `handle_${toSnakeCase(groupName)}_${toSnakeCase(methodName)}`; const paramsType = resolveType(pythonParamsTypeName(method)); - const resultType = method.result ? resolveType(pythonResultTypeName(method)) : null; + const resultType = !isVoidSchema(method.result) ? resolveType(pythonResultTypeName(method)) : null; const handlerField = toSnakeCase(groupName); const handlerMethod = toSnakeCase(methodName); diff --git a/scripts/codegen/typescript.ts b/scripts/codegen/typescript.ts index c2b01f7b4..7dfd5631f 100644 --- a/scripts/codegen/typescript.ts +++ b/scripts/codegen/typescript.ts @@ -15,6 +15,7 @@ import { getSessionEventsSchemaPath, isNodeFullyExperimental, isRpcMethod, + isVoidSchema, postProcessSchema, stripNonAnnotationTitles, writeGeneratedFile, @@ -176,7 +177,7 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; const seenBlocks = new Map(); for (const method of [...allMethods, ...clientSessionMethods]) { - if (method.result) { + if (!isVoidSchema(method.result)) { const compiled = await compile(stripNonAnnotationTitles(method.result), resultTypeName(method), { bannerComment: "", additionalProperties: false, @@ -236,7 +237,7 @@ function emitGroup(node: Record, indent: string, isSession: boo for (const [key, value] of Object.entries(node)) { if (isRpcMethod(value)) { const { rpcMethod, params } = value; - const resultType = value.result ? resultTypeName(value) : "void"; + const resultType = !isVoidSchema(value.result) ? resultTypeName(value) : "void"; const paramsType = paramsTypeName(value); const paramEntries = params?.properties ? Object.entries(params.properties).filter(([k]) => k !== "sessionId") : []; @@ -326,7 +327,7 @@ function emitClientSessionApiRegistration(clientSchema: Record) const name = handlerMethodName(method.rpcMethod); const hasParams = method.params?.properties && Object.keys(method.params.properties).length > 0; const pType = hasParams ? paramsTypeName(method) : ""; - const rType = method.result ? resultTypeName(method) : "void"; + const rType = !isVoidSchema(method.result) ? resultTypeName(method) : "void"; if (hasParams) { lines.push(` ${name}(params: ${pType}): Promise<${rType}>;`); diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index 6fd1a617e..0bc8bc950 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -133,6 +133,16 @@ export function isObjectSchema(schema: JSONSchema7 | null | undefined): boolean return false; } +/** + * Returns true if the schema represents a void/null result (type: "null"). + * These carry a title for languages that need a named empty type (e.g., Go) + * but should be treated as void in other languages. + */ +export function isVoidSchema(schema: JSONSchema7 | null | undefined): boolean { + if (!schema) return true; + return schema.type === "null"; +} + export function cloneSchemaForCodegen(value: T): T { if (Array.isArray(value)) { return value.map((item) => cloneSchemaForCodegen(item)) as T; From 41c3f912286a590924b347cc08cf630186f31279 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 14:51:38 +0100 Subject: [PATCH 06/18] Many fixes Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Client.cs | 5 + dotnet/src/Generated/Rpc.cs | 390 +++++------ dotnet/src/Session.cs | 10 +- dotnet/src/Types.cs | 4 +- dotnet/test/ElicitationTests.cs | 14 +- .../MultiClientCommandsElicitationTests.cs | 4 +- dotnet/test/RpcTests.cs | 6 +- dotnet/test/SessionFsTests.cs | 8 +- go/rpc/generated_rpc.go | 660 +++++++++--------- go/session.go | 22 +- nodejs/src/generated/rpc.ts | 4 +- python/copilot/generated/rpc.py | 68 +- scripts/codegen/csharp.ts | 21 +- scripts/codegen/go.ts | 17 + scripts/codegen/python.ts | 10 +- scripts/codegen/utils.ts | 2 +- 16 files changed, 678 insertions(+), 567 deletions(-) diff --git a/dotnet/src/Client.cs b/dotnet/src/Client.cs index 29b49c294..0124008f4 100644 --- a/dotnet/src/Client.cs +++ b/dotnet/src/Client.cs @@ -1043,6 +1043,11 @@ internal static async Task InvokeRpcAsync(JsonRpc rpc, string method, obje return await InvokeRpcAsync(rpc, method, args, null, cancellationToken); } + internal static async Task InvokeRpcAsync(JsonRpc rpc, string method, object?[]? args, CancellationToken cancellationToken) + { + await InvokeRpcAsync(rpc, method, args, null, cancellationToken); + } + internal static async Task InvokeRpcAsync(JsonRpc rpc, string method, object?[]? args, StringBuilder? stderrBuffer, CancellationToken cancellationToken) { try diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 9dcd3c36b..903784562 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -21,7 +21,7 @@ internal static class Diagnostics } /// RPC data type for Ping operations. -public class PingResult +public sealed class PingResult { /// Echoed message (or default greeting). [JsonPropertyName("message")] @@ -37,7 +37,7 @@ public class PingResult } /// RPC data type for Ping operations. -internal class PingRequest +internal sealed class PingRequest { /// Optional message to echo back. [JsonPropertyName("message")] @@ -45,7 +45,7 @@ internal class PingRequest } /// Feature flags indicating what the model supports. -public class ModelCapabilitiesSupports +public sealed class ModelCapabilitiesSupports { /// Whether this model supports vision/image input. [JsonPropertyName("vision")] @@ -57,38 +57,38 @@ public class ModelCapabilitiesSupports } /// Vision-specific limits. -public class ModelCapabilitiesLimitsVision +public sealed class ModelCapabilitiesLimitsVision { /// MIME types the model accepts. [JsonPropertyName("supported_media_types")] public IList SupportedMediaTypes { get => field ??= []; set; } /// Maximum number of images per prompt. - [Range(typeof(long), "1", "long.MaxValue")] + [Range((double)1, (double)long.MaxValue)] [JsonPropertyName("max_prompt_images")] public long MaxPromptImages { get; set; } /// Maximum image size in bytes. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_image_size")] public long MaxPromptImageSize { get; set; } } /// Token limits for prompts, outputs, and context window. -public class ModelCapabilitiesLimits +public sealed class ModelCapabilitiesLimits { /// Maximum number of prompt/input tokens. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_tokens")] public long? MaxPromptTokens { get; set; } /// Maximum number of output/completion tokens. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_output_tokens")] public long? MaxOutputTokens { get; set; } /// Maximum total context window size in tokens. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_context_window_tokens")] public long MaxContextWindowTokens { get; set; } @@ -98,7 +98,7 @@ public class ModelCapabilitiesLimits } /// Model capabilities and limits. -public class ModelCapabilities +public sealed class ModelCapabilities { /// Feature flags indicating what the model supports. [JsonPropertyName("supports")] @@ -110,7 +110,7 @@ public class ModelCapabilities } /// Policy state (if applicable). -public class ModelPolicy +public sealed class ModelPolicy { /// Current policy state for this model. [JsonPropertyName("state")] @@ -122,7 +122,7 @@ public class ModelPolicy } /// Billing information. -public class ModelBilling +public sealed class ModelBilling { /// Billing cost multiplier relative to the base rate. [JsonPropertyName("multiplier")] @@ -130,7 +130,7 @@ public class ModelBilling } /// RPC data type for Model operations. -public class Model +public sealed class Model { /// Model identifier (e.g., "claude-sonnet-4.5"). [JsonPropertyName("id")] @@ -162,15 +162,15 @@ public class Model } /// RPC data type for ModelList operations. -public class ModelList +public sealed class ModelList { /// List of available models with full metadata. [JsonPropertyName("models")] - public List Models { get; set; } + public IList Models { get => field ??= []; set; } } /// RPC data type for Tool operations. -public class Tool +public sealed class Tool { /// Tool identifier (e.g., "bash", "grep", "str_replace_editor"). [JsonPropertyName("name")] @@ -194,15 +194,15 @@ public class Tool } /// RPC data type for ToolList operations. -public class ToolList +public sealed class ToolList { /// List of available built-in tools with metadata. [JsonPropertyName("tools")] - public List Tools { get; set; } + public IList Tools { get => field ??= []; set; } } /// RPC data type for ToolsList operations. -internal class ToolsListRequest +internal sealed class ToolsListRequest { /// Optional model ID — when provided, the returned tool list reflects model-specific overrides. [JsonPropertyName("model")] @@ -210,14 +210,14 @@ internal class ToolsListRequest } /// RPC data type for AccountQuotaSnapshot operations. -public class AccountQuotaSnapshot +public sealed class AccountQuotaSnapshot { /// Number of requests included in the entitlement. [JsonPropertyName("entitlementRequests")] public long EntitlementRequests { get; set; } /// Number of requests used so far this period. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("usedRequests")] public long UsedRequests { get; set; } @@ -226,7 +226,7 @@ public class AccountQuotaSnapshot public double RemainingPercentage { get; set; } /// Number of overage requests made this period. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("overage")] public long Overage { get; set; } @@ -240,7 +240,7 @@ public class AccountQuotaSnapshot } /// RPC data type for AccountQuota operations. -public class AccountQuota +public sealed class AccountQuota { /// Quota snapshots keyed by type (e.g., chat, completions, premium_interactions). [JsonPropertyName("quotaSnapshots")] @@ -248,7 +248,7 @@ public class AccountQuota } /// RPC data type for DiscoveredMcpServer operations. -public class DiscoveredMcpServer +public sealed class DiscoveredMcpServer { /// Server name (config key). [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] @@ -269,15 +269,15 @@ public class DiscoveredMcpServer } /// RPC data type for McpDiscover operations. -public class McpDiscoverResult +public sealed class McpDiscoverResult { /// MCP servers discovered from all sources. [JsonPropertyName("servers")] - public List Servers { get; set; } + public IList Servers { get => field ??= []; set; } } /// RPC data type for McpDiscover operations. -internal class McpDiscoverRequest +internal sealed class McpDiscoverRequest { /// Working directory used as context for discovery (e.g., plugin resolution). [JsonPropertyName("workingDirectory")] @@ -285,7 +285,7 @@ internal class McpDiscoverRequest } /// RPC data type for SessionFsSetProvider operations. -public class SessionFsSetProviderResult +public sealed class SessionFsSetProviderResult { /// Whether the provider was set successfully. [JsonPropertyName("success")] @@ -293,7 +293,7 @@ public class SessionFsSetProviderResult } /// RPC data type for SessionFsSetProvider operations. -internal class SessionFsSetProviderRequest +internal sealed class SessionFsSetProviderRequest { /// Initial working directory for sessions. [JsonPropertyName("initialCwd")] @@ -310,7 +310,7 @@ internal class SessionFsSetProviderRequest /// RPC data type for SessionsFork operations. [Experimental(Diagnostics.Experimental)] -public class SessionsForkResult +public sealed class SessionsForkResult { /// The new forked session's ID. [JsonPropertyName("sessionId")] @@ -319,7 +319,7 @@ public class SessionsForkResult /// RPC data type for SessionsFork operations. [Experimental(Diagnostics.Experimental)] -internal class SessionsForkRequest +internal sealed class SessionsForkRequest { /// Source session ID to fork from. [JsonPropertyName("sessionId")] @@ -331,7 +331,7 @@ internal class SessionsForkRequest } /// RPC data type for Log operations. -public class LogResult +public sealed class LogResult { /// The unique identifier of the emitted session event. [JsonPropertyName("eventId")] @@ -339,7 +339,7 @@ public class LogResult } /// RPC data type for Log operations. -internal class LogRequest +internal sealed class LogRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -365,7 +365,7 @@ internal class LogRequest } /// RPC data type for ModelCurrent operations. -public class ModelCurrent +public sealed class ModelCurrent { /// Currently active model identifier. [JsonPropertyName("modelId")] @@ -373,7 +373,7 @@ public class ModelCurrent } /// RPC data type for SessionModelGetCurrent operations. -internal class SessionModelGetCurrentRequest +internal sealed class SessionModelGetCurrentRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -381,7 +381,7 @@ internal class SessionModelGetCurrentRequest } /// RPC data type for ModelSwitchTo operations. -public class ModelSwitchToResult +public sealed class ModelSwitchToResult { /// Currently active model identifier after the switch. [JsonPropertyName("modelId")] @@ -389,7 +389,7 @@ public class ModelSwitchToResult } /// Feature flags indicating what the model supports. -public class ModelCapabilitiesOverrideSupports +public sealed class ModelCapabilitiesOverrideSupports { /// Gets or sets the vision value. [JsonPropertyName("vision")] @@ -401,38 +401,38 @@ public class ModelCapabilitiesOverrideSupports } /// RPC data type for ModelCapabilitiesOverrideLimitsVision operations. -public class ModelCapabilitiesOverrideLimitsVision +public sealed class ModelCapabilitiesOverrideLimitsVision { /// MIME types the model accepts. [JsonPropertyName("supported_media_types")] public IList? SupportedMediaTypes { get; set; } /// Maximum number of images per prompt. - [Range(typeof(long), "1", "long.MaxValue")] + [Range((double)1, (double)long.MaxValue)] [JsonPropertyName("max_prompt_images")] public long? MaxPromptImages { get; set; } /// Maximum image size in bytes. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_image_size")] public long? MaxPromptImageSize { get; set; } } /// Token limits for prompts, outputs, and context window. -public class ModelCapabilitiesOverrideLimits +public sealed class ModelCapabilitiesOverrideLimits { /// Gets or sets the max_prompt_tokens value. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_tokens")] public long? MaxPromptTokens { get; set; } /// Gets or sets the max_output_tokens value. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_output_tokens")] public long? MaxOutputTokens { get; set; } /// Maximum total context window size in tokens. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_context_window_tokens")] public long? MaxContextWindowTokens { get; set; } @@ -442,7 +442,7 @@ public class ModelCapabilitiesOverrideLimits } /// Override individual model capabilities resolved by the runtime. -public class ModelCapabilitiesOverride +public sealed class ModelCapabilitiesOverride { /// Feature flags indicating what the model supports. [JsonPropertyName("supports")] @@ -454,7 +454,7 @@ public class ModelCapabilitiesOverride } /// RPC data type for ModelSwitchTo operations. -internal class ModelSwitchToRequest +internal sealed class ModelSwitchToRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -474,7 +474,7 @@ internal class ModelSwitchToRequest } /// RPC data type for SessionModeGet operations. -internal class SessionModeGetRequest +internal sealed class SessionModeGetRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -482,7 +482,7 @@ internal class SessionModeGetRequest } /// RPC data type for ModeSet operations. -internal class ModeSetRequest +internal sealed class ModeSetRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -494,7 +494,7 @@ internal class ModeSetRequest } /// RPC data type for Plan operations. -public class Plan +public sealed class Plan { /// Whether the plan file exists in the workspace. [JsonPropertyName("exists")] @@ -510,7 +510,7 @@ public class Plan } /// RPC data type for SessionPlanRead operations. -internal class SessionPlanReadRequest +internal sealed class SessionPlanReadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -518,7 +518,7 @@ internal class SessionPlanReadRequest } /// RPC data type for PlanUpdate operations. -internal class PlanUpdateRequest +internal sealed class PlanUpdateRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -530,7 +530,7 @@ internal class PlanUpdateRequest } /// RPC data type for SessionPlanDelete operations. -internal class SessionPlanDeleteRequest +internal sealed class SessionPlanDeleteRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -538,7 +538,7 @@ internal class SessionPlanDeleteRequest } /// RPC data type for WorkspaceFiles operations. -public class WorkspaceFiles +public sealed class WorkspaceFiles { /// Relative file paths in the workspace files directory. [JsonPropertyName("files")] @@ -546,7 +546,7 @@ public class WorkspaceFiles } /// RPC data type for SessionWorkspaceListFiles operations. -internal class SessionWorkspaceListFilesRequest +internal sealed class SessionWorkspaceListFilesRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -554,7 +554,7 @@ internal class SessionWorkspaceListFilesRequest } /// RPC data type for WorkspaceReadFile operations. -public class WorkspaceReadFileResult +public sealed class WorkspaceReadFileResult { /// File content as a UTF-8 string. [JsonPropertyName("content")] @@ -562,7 +562,7 @@ public class WorkspaceReadFileResult } /// RPC data type for WorkspaceReadFile operations. -internal class WorkspaceReadFileRequest +internal sealed class WorkspaceReadFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -574,7 +574,7 @@ internal class WorkspaceReadFileRequest } /// RPC data type for WorkspaceCreateFile operations. -internal class WorkspaceCreateFileRequest +internal sealed class WorkspaceCreateFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -591,7 +591,7 @@ internal class WorkspaceCreateFileRequest /// RPC data type for FleetStart operations. [Experimental(Diagnostics.Experimental)] -public class FleetStartResult +public sealed class FleetStartResult { /// Whether fleet mode was successfully activated. [JsonPropertyName("started")] @@ -600,7 +600,7 @@ public class FleetStartResult /// RPC data type for FleetStart operations. [Experimental(Diagnostics.Experimental)] -internal class FleetStartRequest +internal sealed class FleetStartRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -612,7 +612,7 @@ internal class FleetStartRequest } /// RPC data type for Agent operations. -public class Agent +public sealed class Agent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -629,16 +629,16 @@ public class Agent /// RPC data type for AgentList operations. [Experimental(Diagnostics.Experimental)] -public class AgentList +public sealed class AgentList { /// Available custom agents. [JsonPropertyName("agents")] - public List Agents { get; set; } + public IList Agents { get => field ??= []; set; } } /// RPC data type for SessionAgentList operations. [Experimental(Diagnostics.Experimental)] -internal class SessionAgentListRequest +internal sealed class SessionAgentListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -646,7 +646,7 @@ internal class SessionAgentListRequest } /// RPC data type for AgentCurrentAgent operations. -public class AgentCurrentAgent +public sealed class AgentCurrentAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -663,7 +663,7 @@ public class AgentCurrentAgent /// RPC data type for AgentCurrent operations. [Experimental(Diagnostics.Experimental)] -public class AgentCurrent +public sealed class AgentCurrent { /// Currently selected custom agent, or null if using the default agent. [JsonPropertyName("agent")] @@ -672,7 +672,7 @@ public class AgentCurrent /// RPC data type for SessionAgentGetCurrent operations. [Experimental(Diagnostics.Experimental)] -internal class SessionAgentGetCurrentRequest +internal sealed class SessionAgentGetCurrentRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -680,7 +680,7 @@ internal class SessionAgentGetCurrentRequest } /// The newly selected custom agent. -public class AgentSelectAgent +public sealed class AgentSelectAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -697,7 +697,7 @@ public class AgentSelectAgent /// RPC data type for AgentSelect operations. [Experimental(Diagnostics.Experimental)] -public class AgentSelectResult +public sealed class AgentSelectResult { /// The newly selected custom agent. [JsonPropertyName("agent")] @@ -706,7 +706,7 @@ public class AgentSelectResult /// RPC data type for AgentSelect operations. [Experimental(Diagnostics.Experimental)] -internal class AgentSelectRequest +internal sealed class AgentSelectRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -718,7 +718,7 @@ internal class AgentSelectRequest } /// RPC data type for SessionAgentDeselect operations. -internal class SessionAgentDeselectRequest +internal sealed class SessionAgentDeselectRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -726,7 +726,7 @@ internal class SessionAgentDeselectRequest } /// RPC data type for AgentReloadAgent operations. -public class AgentReloadAgent +public sealed class AgentReloadAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -743,16 +743,16 @@ public class AgentReloadAgent /// RPC data type for AgentReload operations. [Experimental(Diagnostics.Experimental)] -public class AgentReload +public sealed class AgentReload { /// Reloaded custom agents. [JsonPropertyName("agents")] - public List Agents { get; set; } + public IList Agents { get => field ??= []; set; } } /// RPC data type for SessionAgentReload operations. [Experimental(Diagnostics.Experimental)] -internal class SessionAgentReloadRequest +internal sealed class SessionAgentReloadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -760,7 +760,7 @@ internal class SessionAgentReloadRequest } /// RPC data type for Skill operations. -public class Skill +public sealed class Skill { /// Unique identifier for the skill. [JsonPropertyName("name")] @@ -789,16 +789,16 @@ public class Skill /// RPC data type for SkillList operations. [Experimental(Diagnostics.Experimental)] -public class SkillList +public sealed class SkillList { /// Available skills. [JsonPropertyName("skills")] - public List Skills { get; set; } + public IList Skills { get => field ??= []; set; } } /// RPC data type for SessionSkillsList operations. [Experimental(Diagnostics.Experimental)] -internal class SessionSkillsListRequest +internal sealed class SessionSkillsListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -807,7 +807,7 @@ internal class SessionSkillsListRequest /// RPC data type for SkillsEnable operations. [Experimental(Diagnostics.Experimental)] -internal class SkillsEnableRequest +internal sealed class SkillsEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -820,7 +820,7 @@ internal class SkillsEnableRequest /// RPC data type for SkillsDisable operations. [Experimental(Diagnostics.Experimental)] -internal class SkillsDisableRequest +internal sealed class SkillsDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -832,7 +832,7 @@ internal class SkillsDisableRequest } /// RPC data type for SessionSkillsReload operations. -internal class SessionSkillsReloadRequest +internal sealed class SessionSkillsReloadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -840,7 +840,7 @@ internal class SessionSkillsReloadRequest } /// RPC data type for McpServer operations. -public class McpServer +public sealed class McpServer { /// Server name (config key). [RegularExpression("^[0-9a-zA-Z_.@-]+(\\/[0-9a-zA-Z_.@-]+)*$")] @@ -860,18 +860,18 @@ public class McpServer public string? Error { get; set; } } -/// RPC data type for McpList operations. +/// RPC data type for McpServerList operations. [Experimental(Diagnostics.Experimental)] -public class McpList +public sealed class McpServerList { /// Configured MCP servers. [JsonPropertyName("servers")] - public List Servers { get; set; } + public IList Servers { get => field ??= []; set; } } /// RPC data type for SessionMcpList operations. [Experimental(Diagnostics.Experimental)] -internal class SessionMcpListRequest +internal sealed class SessionMcpListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -880,7 +880,7 @@ internal class SessionMcpListRequest /// RPC data type for McpEnable operations. [Experimental(Diagnostics.Experimental)] -internal class McpEnableRequest +internal sealed class McpEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -894,7 +894,7 @@ internal class McpEnableRequest /// RPC data type for McpDisable operations. [Experimental(Diagnostics.Experimental)] -internal class McpDisableRequest +internal sealed class McpDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -907,7 +907,7 @@ internal class McpDisableRequest } /// RPC data type for SessionMcpReload operations. -internal class SessionMcpReloadRequest +internal sealed class SessionMcpReloadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -915,7 +915,7 @@ internal class SessionMcpReloadRequest } /// RPC data type for Plugin operations. -public class Plugin +public sealed class Plugin { /// Plugin name. [JsonPropertyName("name")] @@ -936,16 +936,16 @@ public class Plugin /// RPC data type for PluginList operations. [Experimental(Diagnostics.Experimental)] -public class PluginList +public sealed class PluginList { /// Installed plugins. [JsonPropertyName("plugins")] - public List Plugins { get; set; } + public IList Plugins { get => field ??= []; set; } } /// RPC data type for SessionPluginsList operations. [Experimental(Diagnostics.Experimental)] -internal class SessionPluginsListRequest +internal sealed class SessionPluginsListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -953,7 +953,7 @@ internal class SessionPluginsListRequest } /// RPC data type for Extension operations. -public class Extension +public sealed class Extension { /// Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper'). [JsonPropertyName("id")] @@ -978,16 +978,16 @@ public class Extension /// RPC data type for ExtensionList operations. [Experimental(Diagnostics.Experimental)] -public class ExtensionList +public sealed class ExtensionList { /// Discovered extensions and their current status. [JsonPropertyName("extensions")] - public List Extensions { get; set; } + public IList Extensions { get => field ??= []; set; } } /// RPC data type for SessionExtensionsList operations. [Experimental(Diagnostics.Experimental)] -internal class SessionExtensionsListRequest +internal sealed class SessionExtensionsListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -996,7 +996,7 @@ internal class SessionExtensionsListRequest /// RPC data type for ExtensionsEnable operations. [Experimental(Diagnostics.Experimental)] -internal class ExtensionsEnableRequest +internal sealed class ExtensionsEnableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1009,7 +1009,7 @@ internal class ExtensionsEnableRequest /// RPC data type for ExtensionsDisable operations. [Experimental(Diagnostics.Experimental)] -internal class ExtensionsDisableRequest +internal sealed class ExtensionsDisableRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1021,7 +1021,7 @@ internal class ExtensionsDisableRequest } /// RPC data type for SessionExtensionsReload operations. -internal class SessionExtensionsReloadRequest +internal sealed class SessionExtensionsReloadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1029,7 +1029,7 @@ internal class SessionExtensionsReloadRequest } /// RPC data type for HandleToolCall operations. -public class HandleToolCallResult +public sealed class HandleToolCallResult { /// Whether the tool call result was handled successfully. [JsonPropertyName("success")] @@ -1037,7 +1037,7 @@ public class HandleToolCallResult } /// RPC data type for ToolsHandlePendingToolCall operations. -internal class ToolsHandlePendingToolCallRequest +internal sealed class ToolsHandlePendingToolCallRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1057,7 +1057,7 @@ internal class ToolsHandlePendingToolCallRequest } /// RPC data type for CommandsHandlePendingCommand operations. -public class CommandsHandlePendingCommandResult +public sealed class CommandsHandlePendingCommandResult { /// Whether the command was handled successfully. [JsonPropertyName("success")] @@ -1065,7 +1065,7 @@ public class CommandsHandlePendingCommandResult } /// RPC data type for CommandsHandlePendingCommand operations. -internal class CommandsHandlePendingCommandRequest +internal sealed class CommandsHandlePendingCommandRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1081,7 +1081,7 @@ internal class CommandsHandlePendingCommandRequest } /// The elicitation response (accept with form values, decline, or cancel). -public class UiElicitationResponse +public sealed class UiElicitationResponse { /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). [JsonPropertyName("action")] @@ -1093,7 +1093,7 @@ public class UiElicitationResponse } /// JSON Schema describing the form fields to present to the user. -public class UiElicitationSchema +public sealed class UiElicitationSchema { /// Schema type indicator (always 'object'). [JsonPropertyName("type")] @@ -1109,7 +1109,7 @@ public class UiElicitationSchema } /// RPC data type for UiElicitation operations. -internal class UiElicitationRequest +internal sealed class UiElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1125,7 +1125,7 @@ internal class UiElicitationRequest } /// RPC data type for UiElicitation operations. -public class UiElicitationResult +public sealed class UiElicitationResult { /// Whether the response was accepted. False if the request was already resolved by another client. [JsonPropertyName("success")] @@ -1133,7 +1133,7 @@ public class UiElicitationResult } /// RPC data type for HandlePendingElicitation operations. -internal class HandlePendingElicitationRequest +internal sealed class HandlePendingElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1149,7 +1149,7 @@ internal class HandlePendingElicitationRequest } /// RPC data type for PermissionRequest operations. -public class PermissionRequestResult +public sealed class PermissionRequestResult { /// Whether the permission request was handled successfully. [JsonPropertyName("success")] @@ -1157,7 +1157,7 @@ public class PermissionRequestResult } /// RPC data type for PermissionDecision operations. -internal class PermissionDecisionRequest +internal sealed class PermissionDecisionRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1173,7 +1173,7 @@ internal class PermissionDecisionRequest } /// RPC data type for ShellExec operations. -public class ShellExecResult +public sealed class ShellExecResult { /// Unique identifier for tracking streamed output. [JsonPropertyName("processId")] @@ -1181,7 +1181,7 @@ public class ShellExecResult } /// RPC data type for ShellExec operations. -internal class ShellExecRequest +internal sealed class ShellExecRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1196,14 +1196,14 @@ internal class ShellExecRequest public string? Cwd { get; set; } /// Timeout in milliseconds (default: 30000). - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("timeout")] public TimeSpan? Timeout { get; set; } } /// RPC data type for ShellKill operations. -public class ShellKillResult +public sealed class ShellKillResult { /// Whether the signal was sent successfully. [JsonPropertyName("killed")] @@ -1211,7 +1211,7 @@ public class ShellKillResult } /// RPC data type for ShellKill operations. -internal class ShellKillRequest +internal sealed class ShellKillRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1227,54 +1227,54 @@ internal class ShellKillRequest } /// Post-compaction context window usage breakdown. -public class HistoryCompactContextWindow +public sealed class HistoryCompactContextWindow { /// Maximum token count for the model's context window. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] public long TokenLimit { get; set; } /// Current total tokens in the context window (system + conversation + tool definitions). - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("currentTokens")] public long CurrentTokens { get; set; } /// Current number of messages in the conversation. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesLength")] public long MessagesLength { get; set; } /// Token count from system message(s). - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } /// Token count from non-system messages (user, assistant, tool). - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } /// Token count from tool definitions. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } } /// RPC data type for HistoryCompact operations. [Experimental(Diagnostics.Experimental)] -public class HistoryCompact +public sealed class HistoryCompact { /// Whether compaction completed successfully. [JsonPropertyName("success")] public bool Success { get; set; } /// Number of tokens freed by compaction. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokensRemoved")] public long TokensRemoved { get; set; } /// Number of messages removed during compaction. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesRemoved")] public long MessagesRemoved { get; set; } @@ -1285,7 +1285,7 @@ public class HistoryCompact /// RPC data type for SessionHistoryCompact operations. [Experimental(Diagnostics.Experimental)] -internal class SessionHistoryCompactRequest +internal sealed class SessionHistoryCompactRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1294,17 +1294,17 @@ internal class SessionHistoryCompactRequest /// RPC data type for HistoryTruncate operations. [Experimental(Diagnostics.Experimental)] -public class HistoryTruncateResult +public sealed class HistoryTruncateResult { /// Number of events that were removed. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventsRemoved")] public long EventsRemoved { get; set; } } /// RPC data type for HistoryTruncate operations. [Experimental(Diagnostics.Experimental)] -internal class HistoryTruncateRequest +internal sealed class HistoryTruncateRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1316,7 +1316,7 @@ internal class HistoryTruncateRequest } /// Aggregated code change metrics. -public class UsageMetricsCodeChanges +public sealed class UsageMetricsCodeChanges { /// Total lines of code added. [JsonPropertyName("linesAdded")] @@ -1332,7 +1332,7 @@ public class UsageMetricsCodeChanges } /// Request count and cost metrics for this model. -public class UsageMetricsModelMetricRequests +public sealed class UsageMetricsModelMetricRequests { /// Number of API requests made with this model. [JsonPropertyName("count")] @@ -1344,36 +1344,36 @@ public class UsageMetricsModelMetricRequests } /// Token usage metrics for this model. -public class UsageMetricsModelMetricUsage +public sealed class UsageMetricsModelMetricUsage { /// Total input tokens consumed. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputTokens")] public long InputTokens { get; set; } /// Total output tokens produced. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputTokens")] public long OutputTokens { get; set; } /// Total tokens read from prompt cache. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheReadTokens")] public long CacheReadTokens { get; set; } /// Total tokens written to prompt cache. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheWriteTokens")] public long CacheWriteTokens { get; set; } /// Total output tokens used for reasoning. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("reasoningTokens")] public long? ReasoningTokens { get; set; } } /// RPC data type for UsageMetricsModelMetric operations. -public class UsageMetricsModelMetric +public sealed class UsageMetricsModelMetric { /// Request count and cost metrics for this model. [JsonPropertyName("requests")] @@ -1386,14 +1386,14 @@ public class UsageMetricsModelMetric /// RPC data type for UsageMetrics operations. [Experimental(Diagnostics.Experimental)] -public class UsageMetrics +public sealed class UsageMetrics { /// Total user-initiated premium request cost across all models (may be fractional due to multipliers). [JsonPropertyName("totalPremiumRequestCost")] public double TotalPremiumRequestCost { get; set; } /// Raw count of user-initiated API requests. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalUserRequests")] public long TotalUserRequests { get; set; } @@ -1420,19 +1420,19 @@ public class UsageMetrics public string? CurrentModel { get; set; } /// Input tokens from the most recent main-agent API call. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("lastCallInputTokens")] public long LastCallInputTokens { get; set; } /// Output tokens from the most recent main-agent API call. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("lastCallOutputTokens")] public long LastCallOutputTokens { get; set; } } /// RPC data type for SessionUsageGetMetrics operations. [Experimental(Diagnostics.Experimental)] -internal class SessionUsageGetMetricsRequest +internal sealed class SessionUsageGetMetricsRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1440,7 +1440,7 @@ internal class SessionUsageGetMetricsRequest } /// RPC data type for SessionFsReadFile operations. -public class SessionFsReadFileResult +public sealed class SessionFsReadFileResult { /// File content as UTF-8 string. [JsonPropertyName("content")] @@ -1448,7 +1448,7 @@ public class SessionFsReadFileResult } /// RPC data type for SessionFsReadFile operations. -public class SessionFsReadFileRequest +public sealed class SessionFsReadFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1460,7 +1460,7 @@ public class SessionFsReadFileRequest } /// RPC data type for SessionFsWriteFile operations. -public class SessionFsWriteFileRequest +public sealed class SessionFsWriteFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1475,13 +1475,13 @@ public class SessionFsWriteFileRequest public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } } /// RPC data type for SessionFsAppendFile operations. -public class SessionFsAppendFileRequest +public sealed class SessionFsAppendFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1496,13 +1496,13 @@ public class SessionFsAppendFileRequest public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } } /// RPC data type for SessionFsExists operations. -public class SessionFsExistsResult +public sealed class SessionFsExistsResult { /// Whether the path exists. [JsonPropertyName("exists")] @@ -1510,7 +1510,7 @@ public class SessionFsExistsResult } /// RPC data type for SessionFsExists operations. -public class SessionFsExistsRequest +public sealed class SessionFsExistsRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1522,7 +1522,7 @@ public class SessionFsExistsRequest } /// RPC data type for SessionFsStat operations. -public class SessionFsStatResult +public sealed class SessionFsStatResult { /// Whether the path is a file. [JsonPropertyName("isFile")] @@ -1533,7 +1533,7 @@ public class SessionFsStatResult public bool IsDirectory { get; set; } /// File size in bytes. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("size")] public long Size { get; set; } @@ -1547,7 +1547,7 @@ public class SessionFsStatResult } /// RPC data type for SessionFsStat operations. -public class SessionFsStatRequest +public sealed class SessionFsStatRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1559,7 +1559,7 @@ public class SessionFsStatRequest } /// RPC data type for SessionFsMkdir operations. -public class SessionFsMkdirRequest +public sealed class SessionFsMkdirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1574,13 +1574,13 @@ public class SessionFsMkdirRequest public bool? Recursive { get; set; } /// Optional POSIX-style mode for newly created directories. - [Range(typeof(long), "0", "long.MaxValue")] + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } } /// RPC data type for SessionFsReaddir operations. -public class SessionFsReaddirResult +public sealed class SessionFsReaddirResult { /// Entry names in the directory. [JsonPropertyName("entries")] @@ -1588,7 +1588,7 @@ public class SessionFsReaddirResult } /// RPC data type for SessionFsReaddir operations. -public class SessionFsReaddirRequest +public sealed class SessionFsReaddirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1600,7 +1600,7 @@ public class SessionFsReaddirRequest } /// RPC data type for SessionFsReaddirWithTypesEntry operations. -public class SessionFsReaddirWithTypesEntry +public sealed class SessionFsReaddirWithTypesEntry { /// Entry name. [JsonPropertyName("name")] @@ -1612,15 +1612,15 @@ public class SessionFsReaddirWithTypesEntry } /// RPC data type for SessionFsReaddirWithTypes operations. -public class SessionFsReaddirWithTypesResult +public sealed class SessionFsReaddirWithTypesResult { /// Directory entries with type information. [JsonPropertyName("entries")] - public List Entries { get; set; } + public IList Entries { get => field ??= []; set; } } /// RPC data type for SessionFsReaddirWithTypes operations. -public class SessionFsReaddirWithTypesRequest +public sealed class SessionFsReaddirWithTypesRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1632,7 +1632,7 @@ public class SessionFsReaddirWithTypesRequest } /// RPC data type for SessionFsRm operations. -public class SessionFsRmRequest +public sealed class SessionFsRmRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1652,7 +1652,7 @@ public class SessionFsRmRequest } /// RPC data type for SessionFsRename operations. -public class SessionFsRenameRequest +public sealed class SessionFsRenameRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1853,7 +1853,7 @@ public enum SessionFsReaddirWithTypesEntryType /// Provides server-scoped RPC methods (no session required). -public class ServerRpc +public sealed class ServerRpc { private readonly JsonRpc _rpc; @@ -1895,7 +1895,7 @@ public async Task PingAsync(string? message = null, CancellationToke } /// Provides server-scoped Models APIs. -public class ServerModelsApi +public sealed class ServerModelsApi { private readonly JsonRpc _rpc; @@ -1912,7 +1912,7 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Provides server-scoped Tools APIs. -public class ServerToolsApi +public sealed class ServerToolsApi { private readonly JsonRpc _rpc; @@ -1930,7 +1930,7 @@ public async Task ListAsync(string? model = null, CancellationToken ca } /// Provides server-scoped Account APIs. -public class ServerAccountApi +public sealed class ServerAccountApi { private readonly JsonRpc _rpc; @@ -1947,7 +1947,7 @@ public async Task GetQuotaAsync(CancellationToken cancellationToke } /// Provides server-scoped Mcp APIs. -public class ServerMcpApi +public sealed class ServerMcpApi { private readonly JsonRpc _rpc; @@ -1965,7 +1965,7 @@ public async Task DiscoverAsync(string? workingDirectory = nu } /// Provides server-scoped SessionFs APIs. -public class ServerSessionFsApi +public sealed class ServerSessionFsApi { private readonly JsonRpc _rpc; @@ -1984,7 +1984,7 @@ public async Task SetProviderAsync(string initialCwd /// Provides server-scoped Sessions APIs. [Experimental(Diagnostics.Experimental)] -public class ServerSessionsApi +public sealed class ServerSessionsApi { private readonly JsonRpc _rpc; @@ -2002,7 +2002,7 @@ public async Task ForkAsync(string sessionId, string? toEven } /// Provides typed session-scoped RPC methods. -public class SessionRpc +public sealed class SessionRpc { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2090,7 +2090,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = n } /// Provides session-scoped Model APIs. -public class ModelApi +public sealed class ModelApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2117,7 +2117,7 @@ public async Task SwitchToAsync(string modelId, string? rea } /// Provides session-scoped Mode APIs. -public class ModeApi +public sealed class ModeApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2144,7 +2144,7 @@ public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken } /// Provides session-scoped Plan APIs. -public class PlanApi +public sealed class PlanApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2178,7 +2178,7 @@ public async Task DeleteAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Workspace APIs. -public class WorkspaceApi +public sealed class WorkspaceApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2213,7 +2213,7 @@ public async Task CreateFileAsync(string path, string content, CancellationToken /// Provides session-scoped Fleet APIs. [Experimental(Diagnostics.Experimental)] -public class FleetApi +public sealed class FleetApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2233,7 +2233,7 @@ public async Task StartAsync(string? prompt = null, Cancellati } /// Provides session-scoped Agent APIs. -public class AgentApi +public sealed class AgentApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2285,7 +2285,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = } /// Provides session-scoped Skills APIs. -public class SkillsApi +public sealed class SkillsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2329,7 +2329,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Mcp APIs. -public class McpApi +public sealed class McpApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2342,10 +2342,10 @@ internal McpApi(JsonRpc rpc, string sessionId) /// Calls "session.mcp.list". [Experimental(Diagnostics.Experimental)] - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpListRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.list", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.mcp.list", [request], cancellationToken); } /// Calls "session.mcp.enable". @@ -2374,7 +2374,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) /// Provides session-scoped Plugins APIs. [Experimental(Diagnostics.Experimental)] -public class PluginsApi +public sealed class PluginsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2394,7 +2394,7 @@ public async Task ListAsync(CancellationToken cancellationToken = de } /// Provides session-scoped Extensions APIs. -public class ExtensionsApi +public sealed class ExtensionsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2438,7 +2438,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Tools APIs. -public class ToolsApi +public sealed class ToolsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2458,7 +2458,7 @@ public async Task HandlePendingToolCallAsync(string reques } /// Provides session-scoped Commands APIs. -public class CommandsApi +public sealed class CommandsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2478,7 +2478,7 @@ public async Task HandlePendingCommandAsync( } /// Provides session-scoped Ui APIs. -public class UiApi +public sealed class UiApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2505,7 +2505,7 @@ public async Task HandlePendingElicitationAsync(string requ } /// Provides session-scoped Permissions APIs. -public class PermissionsApi +public sealed class PermissionsApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2525,7 +2525,7 @@ public async Task HandlePendingPermissionRequestAsync(s } /// Provides session-scoped Shell APIs. -public class ShellApi +public sealed class ShellApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2553,7 +2553,7 @@ public async Task KillAsync(string processId, ShellKillSignal? /// Provides session-scoped History APIs. [Experimental(Diagnostics.Experimental)] -public class HistoryApi +public sealed class HistoryApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2581,7 +2581,7 @@ public async Task TruncateAsync(string eventId, Cancellat /// Provides session-scoped Usage APIs. [Experimental(Diagnostics.Experimental)] -public class UsageApi +public sealed class UsageApi { private readonly JsonRpc _rpc; private readonly string _sessionId; @@ -2626,7 +2626,7 @@ public interface ISessionFsHandler } /// Provides all client session API handler groups for a session. -public class ClientSessionApiHandlers +public sealed class ClientSessionApiHandlers { /// Optional handler for SessionFs client session API methods. public ISessionFsHandler? SessionFs { get; set; } @@ -2781,8 +2781,8 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func ConfirmAsync(string message, CancellationToken cancellat Required = ["confirmed"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == UiElicitationAction.Accept + if (result.Action == ElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("confirmed", out var val)) { @@ -822,7 +822,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["selection"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == UiElicitationAction.Accept + if (result.Action == ElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("selection", out var val)) { @@ -854,7 +854,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["value"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == UiElicitationAction.Accept + if (result.Action == ElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("value", out var val)) { @@ -1219,7 +1219,7 @@ internal record SendMessageRequest { public string SessionId { get; init; } = string.Empty; public string Prompt { get; init; } = string.Empty; - public IList? Attachments { get; init; } + public IList? Attachments { get; init; } public string? Mode { get; init; } public string? Traceparent { get; init; } public string? Tracestate { get; init; } diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index f8af58c9b..34e64e140 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -729,7 +729,7 @@ public class ElicitationResult /// /// User action: "accept" (submitted), "decline" (rejected), or "cancel" (dismissed). /// - public UiElicitationAction Action { get; set; } + public ElicitationResponseAction Action { get; set; } /// /// Form values submitted by the user (present when is Accept). @@ -2156,7 +2156,7 @@ protected MessageOptions(MessageOptions? other) /// /// File or data attachments to include with the message. /// - public IList? Attachments { get; set; } + public IList? Attachments { get; set; } /// /// Interaction mode for the message (e.g., "plan", "edit"). /// diff --git a/dotnet/test/ElicitationTests.cs b/dotnet/test/ElicitationTests.cs index f110762d8..5fa1e8ba6 100644 --- a/dotnet/test/ElicitationTests.cs +++ b/dotnet/test/ElicitationTests.cs @@ -80,7 +80,7 @@ public async Task Sends_RequestElicitation_When_Handler_Provided() OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = UiElicitationAction.Accept, + Action = ElicitationResponseAction.Accept, Content = new Dictionary(), }), }); @@ -99,7 +99,7 @@ public async Task Session_With_ElicitationHandler_Reports_Elicitation_Capability OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = UiElicitationAction.Accept, + Action = ElicitationResponseAction.Accept, Content = new Dictionary(), }), }); @@ -194,17 +194,17 @@ public void ElicitationResult_Types_Are_Properly_Structured() { var result = new ElicitationResult { - Action = UiElicitationAction.Accept, + Action = ElicitationResponseAction.Accept, Content = new Dictionary { ["name"] = "Alice" }, }; - Assert.Equal(UiElicitationAction.Accept, result.Action); + Assert.Equal(ElicitationResponseAction.Accept, result.Action); Assert.NotNull(result.Content); Assert.Equal("Alice", result.Content!["name"]); var declined = new ElicitationResult { - Action = UiElicitationAction.Decline, + Action = ElicitationResponseAction.Decline, }; Assert.Null(declined.Content); } @@ -262,7 +262,7 @@ public async Task Session_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = UiElicitationAction.Cancel, + Action = ElicitationResponseAction.Cancel, }); var config = new SessionConfig @@ -281,7 +281,7 @@ public void Resume_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = UiElicitationAction.Cancel, + Action = ElicitationResponseAction.Cancel, }); var config = new ResumeSessionConfig diff --git a/dotnet/test/MultiClientCommandsElicitationTests.cs b/dotnet/test/MultiClientCommandsElicitationTests.cs index cf375c637..02199c4c6 100644 --- a/dotnet/test/MultiClientCommandsElicitationTests.cs +++ b/dotnet/test/MultiClientCommandsElicitationTests.cs @@ -175,7 +175,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.UiElicitationAction.Accept, + Action = Rpc.ElicitationResponseAction.Accept, Content = new Dictionary(), }), DisableResume = true, @@ -229,7 +229,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.UiElicitationAction.Accept, + Action = Rpc.ElicitationResponseAction.Accept, Content = new Dictionary(), }), DisableResume = true, diff --git a/dotnet/test/RpcTests.cs b/dotnet/test/RpcTests.cs index 640db77b7..a978a5f3f 100644 --- a/dotnet/test/RpcTests.cs +++ b/dotnet/test/RpcTests.cs @@ -91,16 +91,14 @@ public async Task Should_Get_And_Set_Session_Mode() Assert.Equal(SessionMode.Interactive, initial); // Switch to plan mode - var planResult = await session.Rpc.Mode.SetAsync(SessionMode.Plan); - Assert.Equal(SessionMode.Plan, planResult); + await session.Rpc.Mode.SetAsync(SessionMode.Plan); // Verify mode persisted var afterPlan = await session.Rpc.Mode.GetAsync(); Assert.Equal(SessionMode.Plan, afterPlan); // Switch back to interactive - var interactiveResult = await session.Rpc.Mode.SetAsync(SessionMode.Interactive); - Assert.Equal(SessionMode.Interactive, interactiveResult); + await session.Rpc.Mode.SetAsync(SessionMode.Interactive); } [Fact] diff --git a/dotnet/test/SessionFsTests.cs b/dotnet/test/SessionFsTests.cs index 6e9ed1c8d..8c55b1120 100644 --- a/dotnet/test/SessionFsTests.cs +++ b/dotnet/test/SessionFsTests.cs @@ -409,8 +409,8 @@ public Task StatAsync(SessionFsStatRequest request, Cancell IsFile = true, IsDirectory = false, Size = info.Length, - Mtime = info.LastWriteTimeUtc.ToString("O"), - Birthtime = info.CreationTimeUtc.ToString("O"), + Mtime = info.LastWriteTimeUtc, + Birthtime = info.CreationTimeUtc, }); } @@ -425,8 +425,8 @@ public Task StatAsync(SessionFsStatRequest request, Cancell IsFile = false, IsDirectory = true, Size = 0, - Mtime = dirInfo.LastWriteTimeUtc.ToString("O"), - Birthtime = dirInfo.CreationTimeUtc.ToString("O"), + Mtime = dirInfo.LastWriteTimeUtc, + Birthtime = dirInfo.CreationTimeUtc, }); } diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index a18ca4b83..0df3415de 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -9,215 +9,222 @@ import ( "errors" "fmt" "github.com/github/copilot-sdk/go/internal/jsonrpc2" + "time" ) type PingResult struct { // Echoed message (or default greeting) - Message string `json:"message"` + Message string `json:"message"` // Server protocol version number - ProtocolVersion int64 `json:"protocolVersion"` + ProtocolVersion int64 `json:"protocolVersion"` // Server timestamp in milliseconds - Timestamp int64 `json:"timestamp"` + Timestamp int64 `json:"timestamp"` } type PingRequest struct { // Optional message to echo back - Message *string `json:"message,omitempty"` + Message *string `json:"message,omitempty"` } type ModelList struct { // List of available models with full metadata - Models []Model `json:"models"` + Models []Model `json:"models"` } type Model struct { - Billing *ModelBilling `json:"billing,omitempty"` - Capabilities ModelCapabilities `json:"capabilities"` + // Billing information + Billing *ModelBilling `json:"billing,omitempty"` + // Model capabilities and limits + Capabilities ModelCapabilities `json:"capabilities"` // Default reasoning effort level (only present if model supports reasoning effort) - DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` + DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"` // Model identifier (e.g., "claude-sonnet-4.5") - ID string `json:"id"` + ID string `json:"id"` // Display name - Name string `json:"name"` - Policy *ModelPolicy `json:"policy,omitempty"` + Name string `json:"name"` + // Policy state (if applicable) + Policy *ModelPolicy `json:"policy,omitempty"` // Supported reasoning effort levels (only present if model supports reasoning effort) - SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` + SupportedReasoningEfforts []string `json:"supportedReasoningEfforts,omitempty"` } // Billing information type ModelBilling struct { // Billing cost multiplier relative to the base rate - Multiplier float64 `json:"multiplier"` + Multiplier float64 `json:"multiplier"` } // Model capabilities and limits type ModelCapabilities struct { - Limits ModelCapabilitiesLimits `json:"limits"` + // Token limits for prompts, outputs, and context window + Limits ModelCapabilitiesLimits `json:"limits"` + // Feature flags indicating what the model supports Supports ModelCapabilitiesSupports `json:"supports"` } // Token limits for prompts, outputs, and context window type ModelCapabilitiesLimits struct { // Maximum total context window size in tokens - MaxContextWindowTokens int64 `json:"max_context_window_tokens"` + MaxContextWindowTokens int64 `json:"max_context_window_tokens"` // Maximum number of output/completion tokens - MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` + MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` // Maximum number of prompt/input tokens - MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` - Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"` + MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` + // Vision-specific limits + Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"` } // Vision-specific limits type ModelCapabilitiesLimitsVision struct { // Maximum image size in bytes - MaxPromptImageSize int64 `json:"max_prompt_image_size"` + MaxPromptImageSize int64 `json:"max_prompt_image_size"` // Maximum number of images per prompt - MaxPromptImages int64 `json:"max_prompt_images"` + MaxPromptImages int64 `json:"max_prompt_images"` // MIME types the model accepts - SupportedMediaTypes []string `json:"supported_media_types"` + SupportedMediaTypes []string `json:"supported_media_types"` } // Feature flags indicating what the model supports type ModelCapabilitiesSupports struct { // Whether this model supports reasoning effort configuration - ReasoningEffort *bool `json:"reasoningEffort,omitempty"` + ReasoningEffort *bool `json:"reasoningEffort,omitempty"` // Whether this model supports vision/image input - Vision *bool `json:"vision,omitempty"` + Vision *bool `json:"vision,omitempty"` } // Policy state (if applicable) type ModelPolicy struct { // Current policy state for this model - State string `json:"state"` + State string `json:"state"` // Usage terms or conditions for this model - Terms string `json:"terms"` + Terms string `json:"terms"` } type ToolList struct { // List of available built-in tools with metadata - Tools []Tool `json:"tools"` + Tools []Tool `json:"tools"` } type Tool struct { // Description of what the tool does - Description string `json:"description"` + Description string `json:"description"` // Optional instructions for how to use this tool effectively - Instructions *string `json:"instructions,omitempty"` + Instructions *string `json:"instructions,omitempty"` // Tool identifier (e.g., "bash", "grep", "str_replace_editor") - Name string `json:"name"` + Name string `json:"name"` // Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP // tools) - NamespacedName *string `json:"namespacedName,omitempty"` + NamespacedName *string `json:"namespacedName,omitempty"` // JSON Schema for the tool's input parameters - Parameters map[string]any `json:"parameters,omitempty"` + Parameters map[string]any `json:"parameters,omitempty"` } type ToolsListRequest struct { // Optional model ID — when provided, the returned tool list reflects model-specific // overrides - Model *string `json:"model,omitempty"` + Model *string `json:"model,omitempty"` } type AccountQuota struct { // Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) - QuotaSnapshots map[string]AccountQuotaSnapshot `json:"quotaSnapshots"` + QuotaSnapshots map[string]AccountQuotaSnapshot `json:"quotaSnapshots"` } -import "time" - type AccountQuotaSnapshot struct { // Number of requests included in the entitlement - EntitlementRequests int64 `json:"entitlementRequests"` + EntitlementRequests int64 `json:"entitlementRequests"` // Number of overage requests made this period - Overage int64 `json:"overage"` + Overage int64 `json:"overage"` // Whether pay-per-request usage is allowed when quota is exhausted - OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` + OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` // Percentage of entitlement remaining - RemainingPercentage float64 `json:"remainingPercentage"` + RemainingPercentage float64 `json:"remainingPercentage"` // Date when the quota resets (ISO 8601) - ResetDate *time.Time `json:"resetDate,omitempty"` + ResetDate *time.Time `json:"resetDate,omitempty"` // Number of requests used so far this period - UsedRequests int64 `json:"usedRequests"` + UsedRequests int64 `json:"usedRequests"` } type MCPConfigList struct { // All MCP servers from user config, keyed by name - Servers map[string]MCPConfigServer `json:"servers"` + Servers map[string]MCPConfigServer `json:"servers"` } // MCP server configuration (local/stdio or remote/http) type MCPConfigServer struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` // Timeout in milliseconds for tool calls to this server. - Timeout *int64 `json:"timeout,omitempty"` + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *MCPConfigType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } type MCPConfigAddResult struct { } type MCPConfigAddRequest struct { - Config MCPConfigAddConfig `json:"config"` + // MCP server configuration (local/stdio or remote/http) + Config MCPConfigAddConfig `json:"config"` // Unique name for the MCP server - Name string `json:"name"` + Name string `json:"name"` } // MCP server configuration (local/stdio or remote/http) type MCPConfigAddConfig struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` // Timeout in milliseconds for tool calls to this server. - Timeout *int64 `json:"timeout,omitempty"` + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *MCPConfigType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } type MCPConfigUpdateResult struct { } type MCPConfigUpdateRequest struct { - Config MCPConfigUpdateConfig `json:"config"` + // MCP server configuration (local/stdio or remote/http) + Config MCPConfigUpdateConfig `json:"config"` // Name of the MCP server to update - Name string `json:"name"` + Name string `json:"name"` } // MCP server configuration (local/stdio or remote/http) type MCPConfigUpdateConfig struct { - Args []string `json:"args,omitempty"` - Command *string `json:"command,omitempty"` - Cwd *string `json:"cwd,omitempty"` - Env map[string]string `json:"env,omitempty"` - FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` - IsDefaultServer *bool `json:"isDefaultServer,omitempty"` + Args []string `json:"args,omitempty"` + Command *string `json:"command,omitempty"` + Cwd *string `json:"cwd,omitempty"` + Env map[string]string `json:"env,omitempty"` + FilterMapping *MCPConfigFilterMapping `json:"filterMapping"` + IsDefaultServer *bool `json:"isDefaultServer,omitempty"` // Timeout in milliseconds for tool calls to this server. - Timeout *int64 `json:"timeout,omitempty"` + Timeout *int64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. - Tools []string `json:"tools,omitempty"` - Type *MCPConfigType `json:"type,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - OauthClientID *string `json:"oauthClientId,omitempty"` - OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` - URL *string `json:"url,omitempty"` + Tools []string `json:"tools,omitempty"` + Type *MCPConfigType `json:"type,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + OauthClientID *string `json:"oauthClientId,omitempty"` + OauthPublicClient *bool `json:"oauthPublicClient,omitempty"` + URL *string `json:"url,omitempty"` } type MCPConfigRemoveResult struct { @@ -225,96 +232,102 @@ type MCPConfigRemoveResult struct { type MCPConfigRemoveRequest struct { // Name of the MCP server to remove - Name string `json:"name"` + Name string `json:"name"` } type MCPDiscoverResult struct { // MCP servers discovered from all sources - Servers []DiscoveredMCPServer `json:"servers"` + Servers []DiscoveredMCPServer `json:"servers"` } type DiscoveredMCPServer struct { // Whether the server is enabled (not in the disabled list) - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Server name (config key) - Name string `json:"name"` - Source MCPServerSource `json:"source"` - Type *DiscoveredMCPServerType `json:"type,omitempty"` + Name string `json:"name"` + // Configuration source + Source MCPServerSource `json:"source"` + // Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio) + Type *DiscoveredMCPServerType `json:"type,omitempty"` } type MCPDiscoverRequest struct { // Working directory used as context for discovery (e.g., plugin resolution) - WorkingDirectory *string `json:"workingDirectory,omitempty"` + WorkingDirectory *string `json:"workingDirectory,omitempty"` } type SessionFSSetProviderResult struct { // Whether the provider was set successfully - Success bool `json:"success"` + Success bool `json:"success"` } type SessionFSSetProviderRequest struct { - Conventions SessionFSSetProviderConventions `json:"conventions"` + // Path conventions used by this filesystem + Conventions SessionFSSetProviderConventions `json:"conventions"` // Initial working directory for sessions - InitialCwd string `json:"initialCwd"` + InitialCwd string `json:"initialCwd"` // Path within each session's SessionFs where the runtime stores files for that session - SessionStatePath string `json:"sessionStatePath"` + SessionStatePath string `json:"sessionStatePath"` } // Experimental: SessionsForkResult is part of an experimental API and may change or be removed. type SessionsForkResult struct { // The new forked session's ID - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } // Experimental: SessionsForkRequest is part of an experimental API and may change or be removed. type SessionsForkRequest struct { // Source session ID to fork from - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` // Optional event ID boundary. When provided, the fork includes only events before this ID // (exclusive). When omitted, all events are included. - ToEventID *string `json:"toEventId,omitempty"` + ToEventID *string `json:"toEventId,omitempty"` } type ModelCurrent struct { // Currently active model identifier - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } type ModelSwitchToResult struct { // Currently active model identifier after the switch - ModelID *string `json:"modelId,omitempty"` + ModelID *string `json:"modelId,omitempty"` } type ModelSwitchToRequest struct { - ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` + // Override individual model capabilities resolved by the runtime + ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` // Model identifier to switch to - ModelID string `json:"modelId"` + ModelID string `json:"modelId"` // Reasoning effort level to use for the model - ReasoningEffort *string `json:"reasoningEffort,omitempty"` + ReasoningEffort *string `json:"reasoningEffort,omitempty"` } // Override individual model capabilities resolved by the runtime type ModelCapabilitiesOverride struct { - Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"` + // Token limits for prompts, outputs, and context window + Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"` + // Feature flags indicating what the model supports Supports *ModelCapabilitiesOverrideSupports `json:"supports,omitempty"` } // Token limits for prompts, outputs, and context window type ModelCapabilitiesOverrideLimits struct { // Maximum total context window size in tokens - MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"` - MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` - MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` - Vision *ModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"` + MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"` + MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"` + MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"` + Vision *ModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"` } type ModelCapabilitiesOverrideLimitsVision struct { // Maximum image size in bytes - MaxPromptImageSize *int64 `json:"max_prompt_image_size,omitempty"` + MaxPromptImageSize *int64 `json:"max_prompt_image_size,omitempty"` // Maximum number of images per prompt - MaxPromptImages *int64 `json:"max_prompt_images,omitempty"` + MaxPromptImages *int64 `json:"max_prompt_images,omitempty"` // MIME types the model accepts - SupportedMediaTypes []string `json:"supported_media_types,omitempty"` + SupportedMediaTypes []string `json:"supported_media_types,omitempty"` } // Feature flags indicating what the model supports @@ -327,16 +340,17 @@ type ModeSetResult struct { } type ModeSetRequest struct { + // The agent mode. Valid values: "interactive", "plan", "autopilot". Mode SessionMode `json:"mode"` } type Plan struct { // The content of the plan file, or null if it does not exist - Content *string `json:"content"` + Content *string `json:"content"` // Whether the plan file exists in the workspace - Exists bool `json:"exists"` + Exists bool `json:"exists"` // Absolute file path of the plan file, or null if workspace is not enabled - Path *string `json:"path"` + Path *string `json:"path"` } type PlanUpdateResult struct { @@ -344,7 +358,7 @@ type PlanUpdateResult struct { type PlanUpdateRequest struct { // The new content for the plan file - Content string `json:"content"` + Content string `json:"content"` } type PlanDelete struct { @@ -352,17 +366,17 @@ type PlanDelete struct { type WorkspaceFiles struct { // Relative file paths in the workspace files directory - Files []string `json:"files"` + Files []string `json:"files"` } type WorkspaceReadFileResult struct { // File content as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` } type WorkspaceReadFileRequest struct { // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } type WorkspaceCreateFileResult struct { @@ -370,72 +384,73 @@ type WorkspaceCreateFileResult struct { type WorkspaceCreateFileRequest struct { // File content to write as a UTF-8 string - Content string `json:"content"` + Content string `json:"content"` // Relative path within the workspace files directory - Path string `json:"path"` + Path string `json:"path"` } // Experimental: FleetStartResult is part of an experimental API and may change or be removed. type FleetStartResult struct { // Whether fleet mode was successfully activated - Started bool `json:"started"` + Started bool `json:"started"` } // Experimental: FleetStartRequest is part of an experimental API and may change or be removed. type FleetStartRequest struct { // Optional user prompt to combine with fleet instructions - Prompt *string `json:"prompt,omitempty"` + Prompt *string `json:"prompt,omitempty"` } // Experimental: AgentList is part of an experimental API and may change or be removed. type AgentList struct { // Available custom agents - Agents []Agent `json:"agents"` + Agents []Agent `json:"agents"` } type Agent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: AgentCurrent is part of an experimental API and may change or be removed. type AgentCurrent struct { // Currently selected custom agent, or null if using the default agent - Agent *AgentCurrentAgent `json:"agent"` + Agent *AgentCurrentAgent `json:"agent"` } type AgentCurrentAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: AgentSelectResult is part of an experimental API and may change or be removed. type AgentSelectResult struct { + // The newly selected custom agent Agent AgentSelectAgent `json:"agent"` } // The newly selected custom agent type AgentSelectAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: AgentSelectRequest is part of an experimental API and may change or be removed. type AgentSelectRequest struct { // Name of the custom agent to select - Name string `json:"name"` + Name string `json:"name"` } type AgentDeselect struct { @@ -444,37 +459,37 @@ type AgentDeselect struct { // Experimental: AgentReload is part of an experimental API and may change or be removed. type AgentReload struct { // Reloaded custom agents - Agents []AgentReloadAgent `json:"agents"` + Agents []AgentReloadAgent `json:"agents"` } type AgentReloadAgent struct { // Description of the agent's purpose - Description string `json:"description"` + Description string `json:"description"` // Human-readable display name - DisplayName string `json:"displayName"` + DisplayName string `json:"displayName"` // Unique identifier of the custom agent - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SkillList is part of an experimental API and may change or be removed. type SkillList struct { // Available skills - Skills []Skill `json:"skills"` + Skills []Skill `json:"skills"` } type Skill struct { // Description of what the skill does - Description string `json:"description"` + Description string `json:"description"` // Whether the skill is currently enabled - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Unique identifier for the skill - Name string `json:"name"` + Name string `json:"name"` // Absolute path to the skill file - Path *string `json:"path,omitempty"` + Path *string `json:"path,omitempty"` // Source location type (e.g., project, personal, plugin) - Source string `json:"source"` + Source string `json:"source"` // Whether the skill can be invoked by the user as a slash command - UserInvocable bool `json:"userInvocable"` + UserInvocable bool `json:"userInvocable"` } // Experimental: SkillsEnableResult is part of an experimental API and may change or be removed. @@ -484,7 +499,7 @@ type SkillsEnableResult struct { // Experimental: SkillsEnableRequest is part of an experimental API and may change or be removed. type SkillsEnableRequest struct { // Name of the skill to enable - Name string `json:"name"` + Name string `json:"name"` } // Experimental: SkillsDisableResult is part of an experimental API and may change or be removed. @@ -494,24 +509,26 @@ type SkillsDisableResult struct { // Experimental: SkillsDisableRequest is part of an experimental API and may change or be removed. type SkillsDisableRequest struct { // Name of the skill to disable - Name string `json:"name"` + Name string `json:"name"` } type SkillsReload struct { } -type MCPList struct { +type MCPServerList struct { // Configured MCP servers - Servers []MCPServer `json:"servers"` + Servers []MCPServer `json:"servers"` } type MCPServer struct { // Error message if the server failed to connect - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Server name (config key) - Name string `json:"name"` - Source *MCPServerSource `json:"source,omitempty"` - Status MCPServerStatus `json:"status"` + Name string `json:"name"` + // Configuration source: user, workspace, plugin, or builtin + Source *MCPServerSource `json:"source,omitempty"` + // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured + Status MCPServerStatus `json:"status"` } type MCPEnableResult struct { @@ -519,7 +536,7 @@ type MCPEnableResult struct { type MCPEnableRequest struct { // Name of the MCP server to enable - ServerName string `json:"serverName"` + ServerName string `json:"serverName"` } type MCPDisableResult struct { @@ -527,7 +544,7 @@ type MCPDisableResult struct { type MCPDisableRequest struct { // Name of the MCP server to disable - ServerName string `json:"serverName"` + ServerName string `json:"serverName"` } type MCPReload struct { @@ -536,35 +553,37 @@ type MCPReload struct { // Experimental: PluginList is part of an experimental API and may change or be removed. type PluginList struct { // Installed plugins - Plugins []PluginElement `json:"plugins"` + Plugins []PluginElement `json:"plugins"` } type PluginElement struct { // Whether the plugin is currently enabled - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled"` // Marketplace the plugin came from - Marketplace string `json:"marketplace"` + Marketplace string `json:"marketplace"` // Plugin name - Name string `json:"name"` + Name string `json:"name"` // Installed version - Version *string `json:"version,omitempty"` + Version *string `json:"version,omitempty"` } // Experimental: ExtensionList is part of an experimental API and may change or be removed. type ExtensionList struct { // Discovered extensions and their current status - Extensions []Extension `json:"extensions"` + Extensions []Extension `json:"extensions"` } type Extension struct { // Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper') - ID string `json:"id"` + ID string `json:"id"` // Extension name (directory name) - Name string `json:"name"` + Name string `json:"name"` // Process ID if the extension is running - PID *int64 `json:"pid,omitempty"` - Source ExtensionSource `json:"source"` - Status ExtensionStatus `json:"status"` + PID *int64 `json:"pid,omitempty"` + // Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) + Source ExtensionSource `json:"source"` + // Current status: running, disabled, failed, or starting + Status ExtensionStatus `json:"status"` } // Experimental: ExtensionsEnableResult is part of an experimental API and may change or be removed. @@ -574,7 +593,7 @@ type ExtensionsEnableResult struct { // Experimental: ExtensionsEnableRequest is part of an experimental API and may change or be removed. type ExtensionsEnableRequest struct { // Source-qualified extension ID to enable - ID string `json:"id"` + ID string `json:"id"` } // Experimental: ExtensionsDisableResult is part of an experimental API and may change or be removed. @@ -584,7 +603,7 @@ type ExtensionsDisableResult struct { // Experimental: ExtensionsDisableRequest is part of an experimental API and may change or be removed. type ExtensionsDisableRequest struct { // Source-qualified extension ID to disable - ID string `json:"id"` + ID string `json:"id"` } type ExtensionsReload struct { @@ -592,60 +611,64 @@ type ExtensionsReload struct { type HandleToolCallResult struct { // Whether the tool call result was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } type ToolsHandlePendingToolCallRequest struct { // Error message if the tool call failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Request ID of the pending tool call - RequestID string `json:"requestId"` - Result *ToolsHandlePendingToolCall `json:"result"` + RequestID string `json:"requestId"` + // Tool call result (string or expanded result object) + Result *ToolsHandlePendingToolCall `json:"result"` } type ToolCallResult struct { // Error message if the tool call failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Type of the tool result - ResultType *string `json:"resultType,omitempty"` + ResultType *string `json:"resultType,omitempty"` // Text result to send back to the LLM - TextResultForLlm string `json:"textResultForLlm"` + TextResultForLlm string `json:"textResultForLlm"` // Telemetry data from tool execution - ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` + ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` } type CommandsHandlePendingCommandResult struct { // Whether the command was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } type CommandsHandlePendingCommandRequest struct { // Error message if the command handler failed - Error *string `json:"error,omitempty"` + Error *string `json:"error,omitempty"` // Request ID from the command invocation event - RequestID string `json:"requestId"` + RequestID string `json:"requestId"` } // The elicitation response (accept with form values, decline, or cancel) type UIElicitationResponse struct { - Action ElicitationResponseAction `json:"action"` + // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) + Action ElicitationResponseAction `json:"action"` + // The form values submitted by the user (present when action is 'accept') Content map[string]*ElicitationFieldValue `json:"content,omitempty"` } type UIElicitationRequest struct { // Message describing what information is needed from the user - Message string `json:"message"` - RequestedSchema UIElicitationSchema `json:"requestedSchema"` + Message string `json:"message"` + // JSON Schema describing the form fields to present to the user + RequestedSchema UIElicitationSchema `json:"requestedSchema"` } // JSON Schema describing the form fields to present to the user type UIElicitationSchema struct { // Form field definitions, keyed by field name - Properties map[string]UIElicitationSchemaProperty `json:"properties"` + Properties map[string]UIElicitationSchemaProperty `json:"properties"` // List of required field names - Required []string `json:"required,omitempty"` + Required []string `json:"required,omitempty"` // Schema type indicator (always 'object') - Type RequestedSchemaType `json:"type"` + Type RequestedSchemaType `json:"type"` } type UIElicitationSchemaProperty struct { @@ -685,24 +708,25 @@ type ElicitationStringOneOfFieldOneOf struct { type UIElicitationResult struct { // Whether the response was accepted. False if the request was already resolved by another // client. - Success bool `json:"success"` + Success bool `json:"success"` } type HandlePendingElicitationRequest struct { // The unique request ID from the elicitation.requested event - RequestID string `json:"requestId"` - Result UIElicitationResponse `json:"result"` + RequestID string `json:"requestId"` + // The elicitation response (accept with form values, decline, or cancel) + Result UIElicitationResponse `json:"result"` } type PermissionRequestResult struct { // Whether the permission request was handled successfully - Success bool `json:"success"` + Success bool `json:"success"` } type PermissionDecisionRequest struct { // Request ID of the pending permission request - RequestID string `json:"requestId"` - Result PermissionDecision `json:"result"` + RequestID string `json:"requestId"` + Result PermissionDecision `json:"result"` } type PermissionDecision struct { @@ -717,169 +741,176 @@ type PermissionDecision struct { // Denied by the organization's content exclusion policy // // Denied by a permission request hook registered by an extension or plugin - Kind Kind `json:"kind"` + Kind Kind `json:"kind"` // Rules that denied the request - Rules []any `json:"rules,omitempty"` + Rules []any `json:"rules,omitempty"` // Optional feedback from the user explaining the denial - Feedback *string `json:"feedback,omitempty"` + Feedback *string `json:"feedback,omitempty"` // Human-readable explanation of why the path was excluded // // Optional message from the hook explaining the denial - Message *string `json:"message,omitempty"` + Message *string `json:"message,omitempty"` // File path that triggered the exclusion - Path *string `json:"path,omitempty"` + Path *string `json:"path,omitempty"` // Whether to interrupt the current agent turn - Interrupt *bool `json:"interrupt,omitempty"` + Interrupt *bool `json:"interrupt,omitempty"` } type LogResult struct { // The unique identifier of the emitted session event - EventID string `json:"eventId"` + EventID string `json:"eventId"` } type LogRequest struct { // When true, the message is transient and not persisted to the session event log on disk - Ephemeral *bool `json:"ephemeral,omitempty"` - Level *SessionLogLevel `json:"level,omitempty"` + Ephemeral *bool `json:"ephemeral,omitempty"` + // Log severity level. Determines how the message is displayed in the timeline. Defaults to + // "info". + Level *SessionLogLevel `json:"level,omitempty"` // Human-readable message - Message string `json:"message"` + Message string `json:"message"` // Optional URL the user can open in their browser for more details - URL *string `json:"url,omitempty"` + URL *string `json:"url,omitempty"` } type ShellExecResult struct { // Unique identifier for tracking streamed output - ProcessID string `json:"processId"` + ProcessID string `json:"processId"` } type ShellExecRequest struct { // Shell command to execute - Command string `json:"command"` + Command string `json:"command"` // Working directory (defaults to session working directory) - Cwd *string `json:"cwd,omitempty"` + Cwd *string `json:"cwd,omitempty"` // Timeout in milliseconds (default: 30000) - Timeout *int64 `json:"timeout,omitempty"` + Timeout *int64 `json:"timeout,omitempty"` } type ShellKillResult struct { // Whether the signal was sent successfully - Killed bool `json:"killed"` + Killed bool `json:"killed"` } type ShellKillRequest struct { // Process identifier returned by shell.exec - ProcessID string `json:"processId"` - Signal *ShellKillSignal `json:"signal,omitempty"` + ProcessID string `json:"processId"` + // Signal to send (default: SIGTERM) + Signal *ShellKillSignal `json:"signal,omitempty"` } // Experimental: HistoryCompact is part of an experimental API and may change or be removed. type HistoryCompact struct { - ContextWindow *HistoryCompactContextWindow `json:"contextWindow,omitempty"` + // Post-compaction context window usage breakdown + ContextWindow *HistoryCompactContextWindow `json:"contextWindow,omitempty"` // Number of messages removed during compaction - MessagesRemoved int64 `json:"messagesRemoved"` + MessagesRemoved int64 `json:"messagesRemoved"` // Whether compaction completed successfully - Success bool `json:"success"` + Success bool `json:"success"` // Number of tokens freed by compaction - TokensRemoved int64 `json:"tokensRemoved"` + TokensRemoved int64 `json:"tokensRemoved"` } // Post-compaction context window usage breakdown type HistoryCompactContextWindow struct { // Token count from non-system messages (user, assistant, tool) - ConversationTokens *int64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Current total tokens in the context window (system + conversation + tool definitions) - CurrentTokens int64 `json:"currentTokens"` + CurrentTokens int64 `json:"currentTokens"` // Current number of messages in the conversation - MessagesLength int64 `json:"messagesLength"` + MessagesLength int64 `json:"messagesLength"` // Token count from system message(s) - SystemTokens *int64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Maximum token count for the model's context window - TokenLimit int64 `json:"tokenLimit"` + TokenLimit int64 `json:"tokenLimit"` // Token count from tool definitions - ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } // Experimental: HistoryTruncateResult is part of an experimental API and may change or be removed. type HistoryTruncateResult struct { // Number of events that were removed - EventsRemoved int64 `json:"eventsRemoved"` + EventsRemoved int64 `json:"eventsRemoved"` } // Experimental: HistoryTruncateRequest is part of an experimental API and may change or be removed. type HistoryTruncateRequest struct { // Event ID to truncate to. This event and all events after it are removed from the session. - EventID string `json:"eventId"` + EventID string `json:"eventId"` } // Experimental: UsageMetrics is part of an experimental API and may change or be removed. type UsageMetrics struct { - CodeChanges UsageMetricsCodeChanges `json:"codeChanges"` + // Aggregated code change metrics + CodeChanges UsageMetricsCodeChanges `json:"codeChanges"` // Currently active model identifier - CurrentModel *string `json:"currentModel,omitempty"` + CurrentModel *string `json:"currentModel,omitempty"` // Input tokens from the most recent main-agent API call - LastCallInputTokens int64 `json:"lastCallInputTokens"` + LastCallInputTokens int64 `json:"lastCallInputTokens"` // Output tokens from the most recent main-agent API call - LastCallOutputTokens int64 `json:"lastCallOutputTokens"` + LastCallOutputTokens int64 `json:"lastCallOutputTokens"` // Per-model token and request metrics, keyed by model identifier - ModelMetrics map[string]UsageMetricsModelMetric `json:"modelMetrics"` + ModelMetrics map[string]UsageMetricsModelMetric `json:"modelMetrics"` // Session start timestamp (epoch milliseconds) - SessionStartTime int64 `json:"sessionStartTime"` + SessionStartTime int64 `json:"sessionStartTime"` // Total time spent in model API calls (milliseconds) - TotalAPIDurationMS float64 `json:"totalApiDurationMs"` + TotalAPIDurationMS float64 `json:"totalApiDurationMs"` // Total user-initiated premium request cost across all models (may be fractional due to // multipliers) - TotalPremiumRequestCost float64 `json:"totalPremiumRequestCost"` + TotalPremiumRequestCost float64 `json:"totalPremiumRequestCost"` // Raw count of user-initiated API requests - TotalUserRequests int64 `json:"totalUserRequests"` + TotalUserRequests int64 `json:"totalUserRequests"` } // Aggregated code change metrics type UsageMetricsCodeChanges struct { // Number of distinct files modified - FilesModifiedCount int64 `json:"filesModifiedCount"` + FilesModifiedCount int64 `json:"filesModifiedCount"` // Total lines of code added - LinesAdded int64 `json:"linesAdded"` + LinesAdded int64 `json:"linesAdded"` // Total lines of code removed - LinesRemoved int64 `json:"linesRemoved"` + LinesRemoved int64 `json:"linesRemoved"` } type UsageMetricsModelMetric struct { + // Request count and cost metrics for this model Requests UsageMetricsModelMetricRequests `json:"requests"` - Usage UsageMetricsModelMetricUsage `json:"usage"` + // Token usage metrics for this model + Usage UsageMetricsModelMetricUsage `json:"usage"` } // Request count and cost metrics for this model type UsageMetricsModelMetricRequests struct { // User-initiated premium request cost (with multiplier applied) - Cost float64 `json:"cost"` + Cost float64 `json:"cost"` // Number of API requests made with this model - Count int64 `json:"count"` + Count int64 `json:"count"` } // Token usage metrics for this model type UsageMetricsModelMetricUsage struct { // Total tokens read from prompt cache - CacheReadTokens int64 `json:"cacheReadTokens"` + CacheReadTokens int64 `json:"cacheReadTokens"` // Total tokens written to prompt cache - CacheWriteTokens int64 `json:"cacheWriteTokens"` + CacheWriteTokens int64 `json:"cacheWriteTokens"` // Total input tokens consumed - InputTokens int64 `json:"inputTokens"` + InputTokens int64 `json:"inputTokens"` // Total output tokens produced - OutputTokens int64 `json:"outputTokens"` + OutputTokens int64 `json:"outputTokens"` // Total output tokens used for reasoning - ReasoningTokens *int64 `json:"reasoningTokens,omitempty"` + ReasoningTokens *int64 `json:"reasoningTokens,omitempty"` } type SessionFSReadFileResult struct { // File content as UTF-8 string - Content string `json:"content"` + Content string `json:"content"` } type SessionFSReadFileRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSWriteFileResult struct { @@ -887,13 +918,13 @@ type SessionFSWriteFileResult struct { type SessionFSWriteFileRequest struct { // Content to write - Content string `json:"content"` + Content string `json:"content"` // Optional POSIX-style mode for newly created files - Mode *int64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSAppendFileResult struct { @@ -901,45 +932,45 @@ type SessionFSAppendFileResult struct { type SessionFSAppendFileRequest struct { // Content to append - Content string `json:"content"` + Content string `json:"content"` // Optional POSIX-style mode for newly created files - Mode *int64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSExistsResult struct { // Whether the path exists - Exists bool `json:"exists"` + Exists bool `json:"exists"` } type SessionFSExistsRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSStatResult struct { // ISO 8601 timestamp of creation - Birthtime time.Time `json:"birthtime"` + Birthtime time.Time `json:"birthtime"` // Whether the path is a directory - IsDirectory bool `json:"isDirectory"` + IsDirectory bool `json:"isDirectory"` // Whether the path is a file - IsFile bool `json:"isFile"` + IsFile bool `json:"isFile"` // ISO 8601 timestamp of last modification - Mtime time.Time `json:"mtime"` + Mtime time.Time `json:"mtime"` // File size in bytes - Size int64 `json:"size"` + Size int64 `json:"size"` } type SessionFSStatRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSMkdirResult struct { @@ -947,43 +978,44 @@ type SessionFSMkdirResult struct { type SessionFSMkdirRequest struct { // Optional POSIX-style mode for newly created directories - Mode *int64 `json:"mode,omitempty"` + Mode *int64 `json:"mode,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Create parent directories as needed - Recursive *bool `json:"recursive,omitempty"` + Recursive *bool `json:"recursive,omitempty"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSReaddirResult struct { // Entry names in the directory - Entries []string `json:"entries"` + Entries []string `json:"entries"` } type SessionFSReaddirRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSReaddirWithTypesResult struct { // Directory entries with type information - Entries []SessionFSReaddirWithTypesEntry `json:"entries"` + Entries []SessionFSReaddirWithTypesEntry `json:"entries"` } type SessionFSReaddirWithTypesEntry struct { // Entry name - Name string `json:"name"` - Type SessionFSReaddirWithTypesEntryType `json:"type"` + Name string `json:"name"` + // Entry type + Type SessionFSReaddirWithTypesEntryType `json:"type"` } type SessionFSReaddirWithTypesRequest struct { // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSRmResult struct { @@ -991,13 +1023,13 @@ type SessionFSRmResult struct { type SessionFSRmRequest struct { // Ignore errors if the path does not exist - Force *bool `json:"force,omitempty"` + Force *bool `json:"force,omitempty"` // Path using SessionFs conventions - Path string `json:"path"` + Path string `json:"path"` // Remove directories and their contents recursively - Recursive *bool `json:"recursive,omitempty"` + Recursive *bool `json:"recursive,omitempty"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` } type SessionFSRenameResult struct { @@ -1005,11 +1037,11 @@ type SessionFSRenameResult struct { type SessionFSRenameRequest struct { // Destination path using SessionFs conventions - Dest string `json:"dest"` + Dest string `json:"dest"` // Target session identifier - SessionID string `json:"sessionId"` + SessionID string `json:"sessionId"` // Source path using SessionFs conventions - Src string `json:"src"` + Src string `json:"src"` } type MCPConfigFilterMappingString string @@ -1023,7 +1055,7 @@ const ( type MCPConfigType string const ( - MCPConfigTypeLocal MCPConfigType = "local" + MCPConfigTypeLocal MCPConfigType = "local" MCPConfigTypeHTTP MCPConfigType = "http" MCPConfigTypeSSE MCPConfigType = "sse" MCPConfigTypeStdio MCPConfigType = "stdio" @@ -1035,20 +1067,20 @@ const ( type MCPServerSource string const ( - MCPServerSourceBuiltin MCPServerSource = "builtin" - MCPServerSourceUser MCPServerSource = "user" - MCPServerSourcePlugin MCPServerSource = "plugin" - MCPServerSourceWorkspace MCPServerSource = "workspace" + MCPServerSourceBuiltin MCPServerSource = "builtin" + MCPServerSourceUser MCPServerSource = "user" + MCPServerSourcePlugin MCPServerSource = "plugin" + MCPServerSourceWorkspace MCPServerSource = "workspace" ) // Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio) type DiscoveredMCPServerType string const ( - DiscoveredMCPServerTypeHTTP DiscoveredMCPServerType = "http" - DiscoveredMCPServerTypeSSE DiscoveredMCPServerType = "sse" - DiscoveredMCPServerTypeStdio DiscoveredMCPServerType = "stdio" - DiscoveredMCPServerTypeMemory DiscoveredMCPServerType = "memory" + DiscoveredMCPServerTypeHTTP DiscoveredMCPServerType = "http" + DiscoveredMCPServerTypeSSE DiscoveredMCPServerType = "sse" + DiscoveredMCPServerTypeStdio DiscoveredMCPServerType = "stdio" + DiscoveredMCPServerTypeMemory DiscoveredMCPServerType = "memory" ) // Path conventions used by this filesystem @@ -1063,29 +1095,29 @@ const ( type SessionMode string const ( - SessionModeAutopilot SessionMode = "autopilot" - SessionModeInteractive SessionMode = "interactive" - SessionModePlan SessionMode = "plan" + SessionModeAutopilot SessionMode = "autopilot" + SessionModeInteractive SessionMode = "interactive" + SessionModePlan SessionMode = "plan" ) // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured type MCPServerStatus string const ( - MCPServerStatusConnected MCPServerStatus = "connected" - MCPServerStatusDisabled MCPServerStatus = "disabled" - MCPServerStatusFailed MCPServerStatus = "failed" - MCPServerStatusNeedsAuth MCPServerStatus = "needs-auth" - MCPServerStatusNotConfigured MCPServerStatus = "not_configured" - MCPServerStatusPending MCPServerStatus = "pending" + MCPServerStatusConnected MCPServerStatus = "connected" + MCPServerStatusDisabled MCPServerStatus = "disabled" + MCPServerStatusFailed MCPServerStatus = "failed" + MCPServerStatusNeedsAuth MCPServerStatus = "needs-auth" + MCPServerStatusNotConfigured MCPServerStatus = "not_configured" + MCPServerStatusPending MCPServerStatus = "pending" ) // Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) type ExtensionSource string const ( - ExtensionSourceUser ExtensionSource = "user" - ExtensionSourceProject ExtensionSource = "project" + ExtensionSourceUser ExtensionSource = "user" + ExtensionSourceProject ExtensionSource = "project" ) // Current status: running, disabled, failed, or starting @@ -1094,8 +1126,8 @@ type ExtensionStatus string const ( ExtensionStatusDisabled ExtensionStatus = "disabled" ExtensionStatusFailed ExtensionStatus = "failed" - ExtensionStatusRunning ExtensionStatus = "running" - ExtensionStatusStarting ExtensionStatus = "starting" + ExtensionStatusRunning ExtensionStatus = "running" + ExtensionStatusStarting ExtensionStatus = "starting" ) // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) @@ -1125,11 +1157,11 @@ const ( type UIElicitationSchemaPropertyNumberType string const ( - UIElicitationSchemaPropertyNumberTypeArray UIElicitationSchemaPropertyNumberType = "array" - UIElicitationSchemaPropertyNumberTypeBoolean UIElicitationSchemaPropertyNumberType = "boolean" - UIElicitationSchemaPropertyNumberTypeInteger UIElicitationSchemaPropertyNumberType = "integer" - UIElicitationSchemaPropertyNumberTypeNumber UIElicitationSchemaPropertyNumberType = "number" - UIElicitationSchemaPropertyNumberTypeString UIElicitationSchemaPropertyNumberType = "string" + UIElicitationSchemaPropertyNumberTypeArray UIElicitationSchemaPropertyNumberType = "array" + UIElicitationSchemaPropertyNumberTypeBoolean UIElicitationSchemaPropertyNumberType = "boolean" + UIElicitationSchemaPropertyNumberTypeInteger UIElicitationSchemaPropertyNumberType = "integer" + UIElicitationSchemaPropertyNumberTypeNumber UIElicitationSchemaPropertyNumberType = "number" + UIElicitationSchemaPropertyNumberTypeString UIElicitationSchemaPropertyNumberType = "string" ) type RequestedSchemaType string @@ -1285,7 +1317,7 @@ func (a *ServerSessionsApi) Fork(ctx context.Context, params *SessionsForkReques // ServerRpc provides typed server-scoped RPC methods. type ServerRpc struct { - common serverApi // Reuse a single struct instead of allocating one for each service on the heap. + common serverApi // Reuse a single struct instead of allocating one for each service on the heap. Models *ServerModelsApi Tools *ServerToolsApi @@ -1320,7 +1352,7 @@ func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { } type sessionApi struct { - client *jsonrpc2.Client + client *jsonrpc2.Client sessionID string } @@ -1645,13 +1677,13 @@ func (a *SkillsApi) Reload(ctx context.Context) (*SkillsReload, error) { type McpApi sessionApi // Experimental: List is an experimental API and may change or be removed in future versions. -func (a *McpApi) List(ctx context.Context) (*MCPList, error) { +func (a *McpApi) List(ctx context.Context) (*MCPServerList, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.mcp.list", req) if err != nil { return nil, err } - var result MCPList + var result MCPServerList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1977,7 +2009,7 @@ func (a *UsageApi) GetMetrics(ctx context.Context) (*UsageMetrics, error) { // SessionRpc provides typed session-scoped RPC methods. type SessionRpc struct { - common sessionApi // Reuse a single struct instead of allocating one for each service on the heap. + common sessionApi // Reuse a single struct instead of allocating one for each service on the heap. Model *ModelApi Mode *ModeApi diff --git a/go/session.go b/go/session.go index d7a781f09..7b5fef697 100644 --- a/go/session.go +++ b/go/session.go @@ -591,13 +591,13 @@ func (s *Session) handleElicitationRequest(elicitCtx ElicitationContext, request s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ RequestID: requestID, Result: rpc.UIElicitationResponse{ - Action: rpc.UIElicitationActionCancel, + Action: rpc.ElicitationResponseActionCancel, }, }) return } - rpcContent := make(map[string]*rpc.UIElicitationContent) + rpcContent := make(map[string]*rpc.ElicitationFieldValue) for k, v := range result.Content { rpcContent[k] = toRPCContent(v) } @@ -605,18 +605,18 @@ func (s *Session) handleElicitationRequest(elicitCtx ElicitationContext, request s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ RequestID: requestID, Result: rpc.UIElicitationResponse{ - Action: rpc.UIElicitationAction(result.Action), + Action: rpc.ElicitationResponseAction(result.Action), Content: rpcContent, }, }) } -// toRPCContent converts an arbitrary value to a *rpc.UIElicitationContent for elicitation responses. -func toRPCContent(v any) *rpc.UIElicitationContent { +// toRPCContent converts an arbitrary value to a *rpc.ElicitationFieldValue for elicitation responses. +func toRPCContent(v any) *rpc.ElicitationFieldValue { if v == nil { return nil } - c := &rpc.UIElicitationContent{} + c := &rpc.ElicitationFieldValue{} switch val := v.(type) { case bool: c.Bool = &val @@ -699,7 +699,7 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err := ui.session.assertElicitation(); err != nil { return false, err } - defaultTrue := &rpc.UIElicitationContent{Bool: Bool(true)} + defaultTrue := &rpc.ElicitationFieldValue{Bool: Bool(true)} rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, RequestedSchema: rpc.UIElicitationSchema{ @@ -716,7 +716,7 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err != nil { return false, err } - if rpcResult.Action == rpc.UIElicitationActionAccept { + if rpcResult.Action == rpc.ElicitationResponseActionAccept { if c, ok := rpcResult.Content["confirmed"]; ok && c != nil && c.Bool != nil { return *c.Bool, nil } @@ -746,7 +746,7 @@ func (ui *SessionUI) Select(ctx context.Context, message string, options []strin if err != nil { return "", false, err } - if rpcResult.Action == rpc.UIElicitationActionAccept { + if rpcResult.Action == rpc.ElicitationResponseActionAccept { if c, ok := rpcResult.Content["selection"]; ok && c != nil && c.String != nil { return *c.String, true, nil } @@ -781,7 +781,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio prop.Format = &format } if opts.Default != "" { - prop.Default = &rpc.UIElicitationContent{String: &opts.Default} + prop.Default = &rpc.ElicitationFieldValue{String: &opts.Default} } } rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ @@ -797,7 +797,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio if err != nil { return "", false, err } - if rpcResult.Action == rpc.UIElicitationActionAccept { + if rpcResult.Action == rpc.ElicitationResponseActionAccept { if c, ok := rpcResult.Content["value"]; ok && c != nil && c.String != nil { return *c.String, true, nil } diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index 7f1341453..30790f023 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -851,7 +851,7 @@ export interface SessionSkillsReloadRequest { } /** @experimental */ -export interface McpList { +export interface McpServerList { /** * Configured MCP servers */ @@ -1864,7 +1864,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin }, mcp: { /** @experimental */ - list: async (): Promise => + list: async (): Promise => connection.sendRequest("session.mcp.list", { sessionId }), /** @experimental */ enable: async (params: Omit): Promise => diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index ddad580e3..c5e0d8942 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -177,6 +177,7 @@ class ModelCapabilitiesLimits: """Maximum number of prompt/input tokens""" vision: ModelCapabilitiesLimitsVision | None = None + """Vision-specific limits""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesLimits': @@ -228,7 +229,10 @@ class ModelCapabilities: """Model capabilities and limits""" limits: ModelCapabilitiesLimits + """Token limits for prompts, outputs, and context window""" + supports: ModelCapabilitiesSupports + """Feature flags indicating what the model supports""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilities': @@ -269,6 +273,8 @@ def to_dict(self) -> dict: @dataclass class Model: capabilities: ModelCapabilities + """Model capabilities and limits""" + id: str """Model identifier (e.g., "claude-sonnet-4.5")""" @@ -276,10 +282,14 @@ class Model: """Display name""" billing: ModelBilling | None = None + """Billing information""" + default_reasoning_effort: str | None = None """Default reasoning effort level (only present if model supports reasoning effort)""" policy: ModelPolicy | None = None + """Policy state (if applicable)""" + supported_reasoning_efforts: list[str] | None = None """Supported reasoning effort levels (only present if model supports reasoning effort)""" @@ -629,6 +639,8 @@ def to_dict(self) -> dict: @dataclass class MCPConfigAddRequest: config: MCPConfigAddConfig + """MCP server configuration (local/stdio or remote/http)""" + name: str """Unique name for the MCP server""" @@ -718,6 +730,8 @@ def to_dict(self) -> dict: @dataclass class MCPConfigUpdateRequest: config: MCPConfigUpdateConfig + """MCP server configuration (local/stdio or remote/http)""" + name: str """Name of the MCP server to update""" @@ -777,7 +791,10 @@ class DiscoveredMCPServer: """Server name (config key)""" source: MCPServerSource + """Configuration source""" + type: DiscoveredMCPServerType | None = None + """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)""" @staticmethod def from_dict(obj: Any) -> 'DiscoveredMCPServer': @@ -855,6 +872,8 @@ class SessionFSSetProviderConventions(Enum): @dataclass class SessionFSSetProviderRequest: conventions: SessionFSSetProviderConventions + """Path conventions used by this filesystem""" + initial_cwd: str """Initial working directory for sessions""" @@ -1040,7 +1059,10 @@ class ModelCapabilitiesOverride: """Override individual model capabilities resolved by the runtime""" limits: ModelCapabilitiesOverrideLimits | None = None + """Token limits for prompts, outputs, and context window""" + supports: ModelCapabilitiesOverrideSupports | None = None + """Feature flags indicating what the model supports""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesOverride': @@ -1063,6 +1085,8 @@ class ModelSwitchToRequest: """Model identifier to switch to""" model_capabilities: ModelCapabilitiesOverride | None = None + """Override individual model capabilities resolved by the runtime""" + reasoning_effort: str | None = None """Reasoning effort level to use for the model""" @@ -1093,6 +1117,7 @@ class SessionMode(Enum): @dataclass class ModeSetRequest: mode: SessionMode + """The agent mode. Valid values: "interactive", "plan", "autopilot".""" @staticmethod def from_dict(obj: Any) -> 'ModeSetRequest': @@ -1369,6 +1394,7 @@ def to_dict(self) -> dict: @dataclass class AgentSelectResult: agent: AgentSelectAgent + """The newly selected custom agent""" @staticmethod def from_dict(obj: Any) -> 'AgentSelectResult': @@ -1550,10 +1576,13 @@ class MCPServer: """Server name (config key)""" status: MCPServerStatus + """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured""" + error: str | None = None """Error message if the server failed to connect""" source: MCPServerSource | None = None + """Configuration source: user, workspace, plugin, or builtin""" @staticmethod def from_dict(obj: Any) -> 'MCPServer': @@ -1575,15 +1604,15 @@ def to_dict(self) -> dict: return result @dataclass -class MCPList: +class MCPServerList: servers: list[MCPServer] """Configured MCP servers""" @staticmethod - def from_dict(obj: Any) -> 'MCPList': + def from_dict(obj: Any) -> 'MCPServerList': assert isinstance(obj, dict) servers = from_list(MCPServer.from_dict, obj.get("servers")) - return MCPList(servers) + return MCPServerList(servers) def to_dict(self) -> dict: result: dict = {} @@ -1694,7 +1723,11 @@ class Extension: """Extension name (directory name)""" source: ExtensionSource + """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" + status: ExtensionStatus + """Current status: running, disabled, failed, or starting""" + pid: int | None = None """Process ID if the extension is running""" @@ -1828,6 +1861,7 @@ class ToolsHandlePendingToolCallRequest: """Error message if the tool call failed""" result: ToolCallResult | str | None = None + """Tool call result (string or expanded result object)""" @staticmethod def from_dict(obj: Any) -> 'ToolsHandlePendingToolCallRequest': @@ -1896,7 +1930,10 @@ class UIElicitationResponse: """The elicitation response (accept with form values, decline, or cancel)""" action: ElicitationResponseAction + """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" + content: dict[str, float | bool | list[str] | str] | None = None + """The form values submitted by the user (present when action is 'accept')""" @staticmethod def from_dict(obj: Any) -> 'UIElicitationResponse': @@ -2097,6 +2134,7 @@ class UIElicitationRequest: """Message describing what information is needed from the user""" requested_schema: UIElicitationSchema + """JSON Schema describing the form fields to present to the user""" @staticmethod def from_dict(obj: Any) -> 'UIElicitationRequest': @@ -2135,6 +2173,7 @@ class HandlePendingElicitationRequest: """The unique request ID from the elicitation.requested event""" result: UIElicitationResponse + """The elicitation response (accept with form values, decline, or cancel)""" @staticmethod def from_dict(obj: Any) -> 'HandlePendingElicitationRequest': @@ -2284,6 +2323,9 @@ class LogRequest: """When true, the message is transient and not persisted to the session event log on disk""" level: SessionLogLevel | None = None + """Log severity level. Determines how the message is displayed in the timeline. Defaults to + "info". + """ url: str | None = None """Optional URL the user can open in their browser for more details""" @@ -2380,6 +2422,7 @@ class ShellKillRequest: """Process identifier returned by shell.exec""" signal: ShellKillSignal | None = None + """Signal to send (default: SIGTERM)""" @staticmethod def from_dict(obj: Any) -> 'ShellKillRequest': @@ -2454,6 +2497,7 @@ class HistoryCompact: """Number of tokens freed by compaction""" context_window: HistoryCompactContextWindow | None = None + """Post-compaction context window usage breakdown""" @staticmethod def from_dict(obj: Any) -> 'HistoryCompact': @@ -2600,7 +2644,10 @@ def to_dict(self) -> dict: @dataclass class UsageMetricsModelMetric: requests: UsageMetricsModelMetricRequests + """Request count and cost metrics for this model""" + usage: UsageMetricsModelMetricUsage + """Token usage metrics for this model""" @staticmethod def from_dict(obj: Any) -> 'UsageMetricsModelMetric': @@ -2619,6 +2666,8 @@ def to_dict(self) -> dict: @dataclass class UsageMetrics: code_changes: UsageMetricsCodeChanges + """Aggregated code change metrics""" + last_call_input_tokens: int """Input tokens from the most recent main-agent API call""" @@ -2949,6 +2998,7 @@ class SessionFSReaddirWithTypesEntry: """Entry name""" type: SessionFSReaddirWithTypesEntryType + """Entry type""" @staticmethod def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry': @@ -3281,11 +3331,11 @@ def skills_disable_request_from_dict(s: Any) -> SkillsDisableRequest: def skills_disable_request_to_dict(x: SkillsDisableRequest) -> Any: return to_class(SkillsDisableRequest, x) -def mcp_list_from_dict(s: Any) -> MCPList: - return MCPList.from_dict(s) +def mcp_server_list_from_dict(s: Any) -> MCPServerList: + return MCPServerList.from_dict(s) -def mcp_list_to_dict(x: MCPList) -> Any: - return to_class(MCPList, x) +def mcp_server_list_to_dict(x: MCPServerList) -> Any: + return to_class(MCPServerList, x) def mcp_enable_request_from_dict(s: Any) -> MCPEnableRequest: return MCPEnableRequest.from_dict(s) @@ -3743,9 +3793,9 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list(self, *, timeout: float | None = None) -> MCPList: + async def list(self, *, timeout: float | None = None) -> MCPServerList: """.. warning:: This API is experimental and may change or be removed in future versions.""" - return MCPList.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + return MCPServerList.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def enable(self, params: MCPEnableRequest, *, timeout: float | None = None) -> None: """.. warning:: This API is experimental and may change or be removed in future versions.""" diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 5cd86b046..0caa777b0 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -232,10 +232,11 @@ function emitDataAnnotations(schema: JSONSchema7, indent: string): string[] { if (schema.exclusiveMaximum === true) namedArgs.push("MaximumIsExclusive = true"); const namedSuffix = namedArgs.length > 0 ? `, ${namedArgs.join(", ")}` : ""; if (schema.type === "integer") { - // Use Range(Type, string, string) overload since RangeAttribute has no long constructor + // Use Range(double, double) for AOT/trimming compatibility. + // The Range(Type, string, string) overload uses TypeConverter which triggers IL2026. const min = hasMin ? String(schema.minimum) : "long.MinValue"; const max = hasMax ? String(schema.maximum) : "long.MaxValue"; - attrs.push(`${indent}[Range(typeof(long), "${min}", "${max}"${namedSuffix})]`); + attrs.push(`${indent}[Range((double)${min}, (double)${max}${namedSuffix})]`); } else { const min = hasMin ? String(schema.minimum) : "double.MinValue"; const max = hasMax ? String(schema.maximum) : "double.MaxValue"; @@ -767,7 +768,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam if (items.type === "object" && items.properties) { const itemClass = (items.title as string) ?? singularPascal(propName); classes.push(emitRpcClass(itemClass, items, "public", classes)); - return isRequired ? `List<${itemClass}>` : `List<${itemClass}>?`; + return isRequired ? `IList<${itemClass}>` : `IList<${itemClass}>?`; } if (items.enum && Array.isArray(items.enum)) { const itemEnum = getOrCreateEnum( @@ -778,7 +779,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam items.description, items.title as string | undefined, ); - return isRequired ? `List<${itemEnum}>` : `List<${itemEnum}>?`; + return isRequired ? `IList<${itemEnum}>` : `IList<${itemEnum}>?`; } const itemType = schemaTypeToCSharp(items, true, rpcKnownTypes); return isRequired ? `IList<${itemType}>` : `IList<${itemType}>?`; @@ -816,7 +817,7 @@ function emitRpcClass(className: string, schema: JSONSchema7, visibility: "publi if (experimentalRpcTypes.has(className)) { lines.push(`[Experimental(Diagnostics.Experimental)]`); } - lines.push(`${visibility} class ${className}`, `{`); + lines.push(`${visibility} sealed class ${className}`, `{`); const props = Object.entries(schema.properties || {}); for (let i = 0; i < props.length; i++) { @@ -882,7 +883,7 @@ function emitServerRpcClasses(node: Record, classes: string[]): // ServerRpc class const srLines: string[] = []; srLines.push(`/// Provides server-scoped RPC methods (no session required).`); - srLines.push(`public class ServerRpc`); + srLines.push(`public sealed class ServerRpc`); srLines.push(`{`); srLines.push(` private readonly JsonRpc _rpc;`); srLines.push(""); @@ -926,7 +927,7 @@ function emitServerApiClass(className: string, node: Record, cl if (groupExperimental) { lines.push(`[Experimental(Diagnostics.Experimental)]`); } - lines.push(`public class ${className}`); + lines.push(`public sealed class ${className}`); lines.push(`{`); lines.push(` private readonly JsonRpc _rpc;`); lines.push(""); @@ -1029,7 +1030,7 @@ function emitSessionRpcClasses(node: Record, classes: string[]) const groups = Object.entries(node).filter(([, v]) => typeof v === "object" && v !== null && !isRpcMethod(v)); const topLevelMethods = Object.entries(node).filter(([, v]) => isRpcMethod(v)); - const srLines = [`/// Provides typed session-scoped RPC methods.`, `public class SessionRpc`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; + const srLines = [`/// Provides typed session-scoped RPC methods.`, `public sealed class SessionRpc`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; srLines.push(` internal SessionRpc(JsonRpc rpc, string sessionId)`, ` {`, ` _rpc = rpc;`, ` _sessionId = sessionId;`); for (const [groupName] of groups) srLines.push(` ${toPascalCase(groupName)} = new ${toPascalCase(groupName)}Api(rpc, sessionId);`); srLines.push(` }`); @@ -1113,7 +1114,7 @@ function emitSessionApiClass(className: string, node: Record, c const displayName = className.replace(/Api$/, ""); const groupExperimental = isNodeFullyExperimental(node); const experimentalAttr = groupExperimental ? `[Experimental(Diagnostics.Experimental)]\n` : ""; - const lines = [`/// Provides session-scoped ${displayName} APIs.`, `${experimentalAttr}public class ${className}`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; + const lines = [`/// Provides session-scoped ${displayName} APIs.`, `${experimentalAttr}public sealed class ${className}`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""]; lines.push(` internal ${className}(JsonRpc rpc, string sessionId)`, ` {`, ` _rpc = rpc;`, ` _sessionId = sessionId;`, ` }`); for (const [key, value] of Object.entries(node)) { @@ -1196,7 +1197,7 @@ function emitClientSessionApiRegistration(clientSchema: Record, } lines.push(`/// Provides all client session API handler groups for a session.`); - lines.push(`public class ClientSessionApiHandlers`); + lines.push(`public sealed class ClientSessionApiHandlers`); lines.push(`{`); for (const { groupName } of groups) { lines.push(` /// Optional handler for ${toPascalCase(groupName)} client session API methods.`); diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 307083b0d..6467f22d3 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -915,6 +915,19 @@ async function generateRpc(schemaPath?: string): Promise { // Post-process quicktype output: fix enum constant names let qtCode = qtResult.lines.filter((l) => !l.startsWith("package ")).join("\n"); + // Extract any imports quicktype emitted (e.g., "time") and hoist them + const qtImports: string[] = []; + qtCode = qtCode.replace(/^import\s+"([^"]+)"\s*$/gm, (_match, imp) => { + qtImports.push(`"${imp}"`); + return ""; + }); + qtCode = qtCode.replace(/^import\s+\(([^)]*)\)\s*$/gm, (_match, block) => { + for (const line of block.split("\n")) { + const trimmed = line.trim(); + if (trimmed) qtImports.push(trimmed); + } + return ""; + }); qtCode = postProcessEnumConstants(qtCode); qtCode = collapsePlaceholderGoStructs(qtCode); // Strip trailing whitespace from quicktype output (gofmt requirement) @@ -965,6 +978,10 @@ async function generateRpc(schemaPath?: string): Promise { imports.push(`"errors"`, `"fmt"`); } imports.push(`"github.com/github/copilot-sdk/go/internal/jsonrpc2"`); + // Add any imports hoisted from quicktype output + for (const qi of qtImports) { + if (!imports.includes(qi)) imports.push(qi); + } lines.push(`import (`); for (const imp of imports) { diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index 7dccfeca9..82a08cae0 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -219,8 +219,16 @@ async function generateSessionEvents(schemaPath?: string): Promise { const resolvedSchema = (schema.definitions?.SessionEvent as JSONSchema7) || schema; const processed = postProcessSchema(resolvedSchema); + // Hoist titled inline schemas (enums etc.) to definitions so quicktype + // uses the schema-defined names instead of its own structural heuristics. + const { rootDefinitions: hoistedRoots, sharedDefinitions } = hoistTitledSchemas({ SessionEvent: processed }); + const hoisted = hoistedRoots.SessionEvent; + if (Object.keys(sharedDefinitions).length > 0) { + hoisted.definitions = { ...hoisted.definitions, ...sharedDefinitions }; + } + const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore()); - await schemaInput.addSource({ name: "SessionEvent", schema: JSON.stringify(processed) }); + await schemaInput.addSource({ name: "SessionEvent", schema: JSON.stringify(hoisted) }); const inputData = new InputData(); inputData.addInput(schemaInput); diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts index 0bc8bc950..225e678b7 100644 --- a/scripts/codegen/utils.ts +++ b/scripts/codegen/utils.ts @@ -254,7 +254,7 @@ function visitSchema( } else { sharedDefinitions[result.title] = result; } - return { $ref: `#/definitions/${result.title}` }; + return { $ref: `#/definitions/${result.title}`, description: result.description } as JSONSchema7; } return result; From ecafa7ab420c50dbc531b61dd8385a4affb2d3b4 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 15:02:53 +0100 Subject: [PATCH 07/18] Regen Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 48 +++++++-------- dotnet/src/Generated/SessionEvents.cs | 8 +-- dotnet/src/Session.cs | 20 +++---- dotnet/src/Types.cs | 2 +- dotnet/test/ElicitationTests.cs | 14 ++--- .../MultiClientCommandsElicitationTests.cs | 4 +- go/generated_session_events.go | 4 +- go/rpc/generated_rpc.go | 36 +++++------ go/session.go | 26 ++++---- nodejs/src/generated/rpc.ts | 42 ++++++------- python/copilot/generated/rpc.py | 60 +++++++++---------- 11 files changed, 132 insertions(+), 132 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 903784562..bad821fc2 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -1081,11 +1081,11 @@ internal sealed class CommandsHandlePendingCommandRequest } /// The elicitation response (accept with form values, decline, or cancel). -public sealed class UiElicitationResponse +public sealed class UIElicitationResponse { /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). [JsonPropertyName("action")] - public ElicitationResponseAction Action { get; set; } + public UIElicitationResponseAction Action { get; set; } /// The form values submitted by the user (present when action is 'accept'). [JsonPropertyName("content")] @@ -1093,7 +1093,7 @@ public sealed class UiElicitationResponse } /// JSON Schema describing the form fields to present to the user. -public sealed class UiElicitationSchema +public sealed class UIElicitationSchema { /// Schema type indicator (always 'object'). [JsonPropertyName("type")] @@ -1108,8 +1108,8 @@ public sealed class UiElicitationSchema public IList? Required { get; set; } } -/// RPC data type for UiElicitation operations. -internal sealed class UiElicitationRequest +/// RPC data type for UIElicitation operations. +internal sealed class UIElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1121,19 +1121,19 @@ internal sealed class UiElicitationRequest /// JSON Schema describing the form fields to present to the user. [JsonPropertyName("requestedSchema")] - public UiElicitationSchema RequestedSchema { get => field ??= new(); set; } + public UIElicitationSchema RequestedSchema { get => field ??= new(); set; } } -/// RPC data type for UiElicitation operations. -public sealed class UiElicitationResult +/// RPC data type for UIElicitation operations. +public sealed class UIElicitationResult { /// Whether the response was accepted. False if the request was already resolved by another client. [JsonPropertyName("success")] public bool Success { get; set; } } -/// RPC data type for HandlePendingElicitation operations. -internal sealed class HandlePendingElicitationRequest +/// RPC data type for UIHandlePendingElicitation operations. +internal sealed class UIHandlePendingElicitationRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1145,7 +1145,7 @@ internal sealed class HandlePendingElicitationRequest /// The elicitation response (accept with form values, decline, or cancel). [JsonPropertyName("result")] - public UiElicitationResponse Result { get => field ??= new(); set; } + public UIElicitationResponse Result { get => field ??= new(); set; } } /// RPC data type for PermissionRequest operations. @@ -1808,8 +1808,8 @@ public enum ExtensionStatus /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum ElicitationResponseAction +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum UIElicitationResponseAction { /// The accept variant. [JsonStringEnumMemberName("accept")] @@ -2490,17 +2490,17 @@ internal UiApi(JsonRpc rpc, string sessionId) } /// Calls "session.ui.elicitation". - public async Task ElicitationAsync(string message, UiElicitationSchema requestedSchema, CancellationToken cancellationToken = default) + public async Task ElicitationAsync(string message, UIElicitationSchema requestedSchema, CancellationToken cancellationToken = default) { - var request = new UiElicitationRequest { SessionId = _sessionId, Message = message, RequestedSchema = requestedSchema }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.elicitation", [request], cancellationToken); + var request = new UIElicitationRequest { SessionId = _sessionId, Message = message, RequestedSchema = requestedSchema }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.elicitation", [request], cancellationToken); } /// Calls "session.ui.handlePendingElicitation". - public async Task HandlePendingElicitationAsync(string requestId, UiElicitationResponse result, CancellationToken cancellationToken = default) + public async Task HandlePendingElicitationAsync(string requestId, UIElicitationResponse result, CancellationToken cancellationToken = default) { - var request = new HandlePendingElicitationRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); + var request = new UIHandlePendingElicitationRequest { SessionId = _sessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); } } @@ -2769,7 +2769,6 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, FuncUI capability changes. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("ui")] - public CapabilitiesChangedUi? Ui { get; set; } + public CapabilitiesChangedUI? Ui { get; set; } } /// Plan approval request with plan content and available user actions. @@ -3744,8 +3744,8 @@ public partial class CommandsChangedCommand } /// UI capability changes. -/// Nested data type for CapabilitiesChangedUi. -public partial class CapabilitiesChangedUi +/// Nested data type for CapabilitiesChangedUI. +public partial class CapabilitiesChangedUI { /// Whether elicitation is now supported. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4164,7 +4164,7 @@ public enum ExtensionsLoadedExtensionStatus [JsonSerializable(typeof(AssistantUsageEvent))] [JsonSerializable(typeof(CapabilitiesChangedData))] [JsonSerializable(typeof(CapabilitiesChangedEvent))] -[JsonSerializable(typeof(CapabilitiesChangedUi))] +[JsonSerializable(typeof(CapabilitiesChangedUI))] [JsonSerializable(typeof(CommandCompletedData))] [JsonSerializable(typeof(CommandCompletedEvent))] [JsonSerializable(typeof(CommandExecuteData))] diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index 7eb9f5351..733b94a71 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -727,7 +727,7 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str try { var result = await handler(context); - await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UiElicitationResponse + await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse { Action = result.Action, Content = result.Content @@ -738,9 +738,9 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str // User handler can throw any exception — attempt to cancel so the request doesn't hang. try { - await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UiElicitationResponse + await Rpc.Ui.HandlePendingElicitationAsync(requestId, new UIElicitationResponse { - Action = ElicitationResponseAction.Cancel + Action = UIElicitationResponseAction.Cancel }); } catch (Exception innerEx) when (innerEx is IOException or ObjectDisposedException) @@ -771,7 +771,7 @@ private sealed class SessionUiApiImpl(CopilotSession session) : ISessionUiApi public async Task ElicitationAsync(ElicitationParams elicitationParams, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new UiElicitationSchema + var schema = new UIElicitationSchema { Type = elicitationParams.RequestedSchema.Type, Properties = elicitationParams.RequestedSchema.Properties, @@ -784,7 +784,7 @@ public async Task ElicitationAsync(ElicitationParams elicitat public async Task ConfirmAsync(string message, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new UiElicitationSchema + var schema = new UIElicitationSchema { Type = "object", Properties = new Dictionary @@ -794,7 +794,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["confirmed"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == ElicitationResponseAction.Accept + if (result.Action == UIElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("confirmed", out var val)) { @@ -812,7 +812,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat public async Task SelectAsync(string message, string[] options, CancellationToken cancellationToken) { session.AssertElicitation(); - var schema = new UiElicitationSchema + var schema = new UIElicitationSchema { Type = "object", Properties = new Dictionary @@ -822,7 +822,7 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat Required = ["selection"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == ElicitationResponseAction.Accept + if (result.Action == UIElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("selection", out var val)) { @@ -847,14 +847,14 @@ public async Task ConfirmAsync(string message, CancellationToken cancellat if (options?.Format != null) field["format"] = options.Format; if (options?.Default != null) field["default"] = options.Default; - var schema = new UiElicitationSchema + var schema = new UIElicitationSchema { Type = "object", Properties = new Dictionary { ["value"] = field }, Required = ["value"] }; var result = await session.Rpc.Ui.ElicitationAsync(message, schema, cancellationToken); - if (result.Action == ElicitationResponseAction.Accept + if (result.Action == UIElicitationResponseAction.Accept && result.Content != null && result.Content.TryGetValue("value", out var val)) { diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 34e64e140..f88d84eb6 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -729,7 +729,7 @@ public class ElicitationResult /// /// User action: "accept" (submitted), "decline" (rejected), or "cancel" (dismissed). /// - public ElicitationResponseAction Action { get; set; } + public UIElicitationResponseAction Action { get; set; } /// /// Form values submitted by the user (present when is Accept). diff --git a/dotnet/test/ElicitationTests.cs b/dotnet/test/ElicitationTests.cs index 5fa1e8ba6..881c67f6c 100644 --- a/dotnet/test/ElicitationTests.cs +++ b/dotnet/test/ElicitationTests.cs @@ -80,7 +80,7 @@ public async Task Sends_RequestElicitation_When_Handler_Provided() OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = ElicitationResponseAction.Accept, + Action = UIElicitationResponseAction.Accept, Content = new Dictionary(), }), }); @@ -99,7 +99,7 @@ public async Task Session_With_ElicitationHandler_Reports_Elicitation_Capability OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = ElicitationResponseAction.Accept, + Action = UIElicitationResponseAction.Accept, Content = new Dictionary(), }), }); @@ -194,17 +194,17 @@ public void ElicitationResult_Types_Are_Properly_Structured() { var result = new ElicitationResult { - Action = ElicitationResponseAction.Accept, + Action = UIElicitationResponseAction.Accept, Content = new Dictionary { ["name"] = "Alice" }, }; - Assert.Equal(ElicitationResponseAction.Accept, result.Action); + Assert.Equal(UIElicitationResponseAction.Accept, result.Action); Assert.NotNull(result.Content); Assert.Equal("Alice", result.Content!["name"]); var declined = new ElicitationResult { - Action = ElicitationResponseAction.Decline, + Action = UIElicitationResponseAction.Decline, }; Assert.Null(declined.Content); } @@ -262,7 +262,7 @@ public async Task Session_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = ElicitationResponseAction.Cancel, + Action = UIElicitationResponseAction.Cancel, }); var config = new SessionConfig @@ -281,7 +281,7 @@ public void Resume_Config_OnElicitationRequest_Is_Cloned() { ElicitationHandler handler = _ => Task.FromResult(new ElicitationResult { - Action = ElicitationResponseAction.Cancel, + Action = UIElicitationResponseAction.Cancel, }); var config = new ResumeSessionConfig diff --git a/dotnet/test/MultiClientCommandsElicitationTests.cs b/dotnet/test/MultiClientCommandsElicitationTests.cs index 02199c4c6..c5571b43e 100644 --- a/dotnet/test/MultiClientCommandsElicitationTests.cs +++ b/dotnet/test/MultiClientCommandsElicitationTests.cs @@ -175,7 +175,7 @@ public async Task Capabilities_Changed_Fires_When_Second_Client_Joins_With_Elici OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.ElicitationResponseAction.Accept, + Action = Rpc.UIElicitationResponseAction.Accept, Content = new Dictionary(), }), DisableResume = true, @@ -229,7 +229,7 @@ public async Task Capabilities_Changed_Fires_When_Elicitation_Provider_Disconnec OnPermissionRequest = PermissionHandler.ApproveAll, OnElicitationRequest = _ => Task.FromResult(new ElicitationResult { - Action = Rpc.ElicitationResponseAction.Accept, + Action = Rpc.UIElicitationResponseAction.Accept, Content = new Dictionary(), }), DisableResume = true, diff --git a/go/generated_session_events.go b/go/generated_session_events.go index 3c64be8f7..b2a2d7248 100644 --- a/go/generated_session_events.go +++ b/go/generated_session_events.go @@ -1535,7 +1535,7 @@ func (*CommandsChangedData) sessionEventData() {} // Session capability change notification type CapabilitiesChangedData struct { // UI capability changes - UI *CapabilitiesChangedUi `json:"ui,omitempty"` + UI *CapabilitiesChangedUI `json:"ui,omitempty"` } func (*CapabilitiesChangedData) sessionEventData() {} @@ -2047,7 +2047,7 @@ type CommandsChangedCommand struct { } // UI capability changes -type CapabilitiesChangedUi struct { +type CapabilitiesChangedUI struct { // Whether elicitation is now supported Elicitation *bool `json:"elicitation,omitempty"` } diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go index 0df3415de..1c949969a 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -649,9 +649,9 @@ type CommandsHandlePendingCommandRequest struct { // The elicitation response (accept with form values, decline, or cancel) type UIElicitationResponse struct { // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - Action ElicitationResponseAction `json:"action"` + Action UIElicitationResponseAction `json:"action"` // The form values submitted by the user (present when action is 'accept') - Content map[string]*ElicitationFieldValue `json:"content,omitempty"` + Content map[string]*UIElicitationFieldValue `json:"content,omitempty"` } type UIElicitationRequest struct { @@ -672,14 +672,14 @@ type UIElicitationSchema struct { } type UIElicitationSchemaProperty struct { - Default *ElicitationFieldValue `json:"default"` + Default *UIElicitationFieldValue `json:"default"` Description *string `json:"description,omitempty"` Enum []string `json:"enum,omitempty"` EnumNames []string `json:"enumNames,omitempty"` Title *string `json:"title,omitempty"` Type UIElicitationSchemaPropertyNumberType `json:"type"` - OneOf []ElicitationStringOneOfFieldOneOf `json:"oneOf,omitempty"` - Items *ElicitationArrayFieldItems `json:"items,omitempty"` + OneOf []UIElicitationStringOneOfFieldOneOf `json:"oneOf,omitempty"` + Items *UIElicitationArrayFieldItems `json:"items,omitempty"` MaxItems *float64 `json:"maxItems,omitempty"` MinItems *float64 `json:"minItems,omitempty"` Format *UIElicitationSchemaPropertyStringFormat `json:"format,omitempty"` @@ -689,18 +689,18 @@ type UIElicitationSchemaProperty struct { Minimum *float64 `json:"minimum,omitempty"` } -type ElicitationArrayFieldItems struct { - Enum []string `json:"enum,omitempty"` - Type *ItemsType `json:"type,omitempty"` - AnyOf []ElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"` +type UIElicitationArrayFieldItems struct { + Enum []string `json:"enum,omitempty"` + Type *ItemsType `json:"type,omitempty"` + AnyOf []UIElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"` } -type ElicitationArrayAnyOfFieldItemsAnyOf struct { +type UIElicitationArrayAnyOfFieldItemsAnyOf struct { Const string `json:"const"` Title string `json:"title"` } -type ElicitationStringOneOfFieldOneOf struct { +type UIElicitationStringOneOfFieldOneOf struct { Const string `json:"const"` Title string `json:"title"` } @@ -711,7 +711,7 @@ type UIElicitationResult struct { Success bool `json:"success"` } -type HandlePendingElicitationRequest struct { +type UIHandlePendingElicitationRequest struct { // The unique request ID from the elicitation.requested event RequestID string `json:"requestId"` // The elicitation response (accept with form values, decline, or cancel) @@ -1131,12 +1131,12 @@ const ( ) // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) -type ElicitationResponseAction string +type UIElicitationResponseAction string const ( - ElicitationResponseActionAccept ElicitationResponseAction = "accept" - ElicitationResponseActionCancel ElicitationResponseAction = "cancel" - ElicitationResponseActionDecline ElicitationResponseAction = "decline" + UIElicitationResponseActionAccept UIElicitationResponseAction = "accept" + UIElicitationResponseActionCancel UIElicitationResponseAction = "cancel" + UIElicitationResponseActionDecline UIElicitationResponseAction = "decline" ) type UIElicitationSchemaPropertyStringFormat string @@ -1219,7 +1219,7 @@ type ToolsHandlePendingToolCall struct { ToolCallResult *ToolCallResult } -type ElicitationFieldValue struct { +type UIElicitationFieldValue struct { Bool *bool Double *float64 String *string @@ -1880,7 +1880,7 @@ func (a *UIApi) Elicitation(ctx context.Context, params *UIElicitationRequest) ( return &result, nil } -func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *HandlePendingElicitationRequest) (*UIElicitationResult, error) { +func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *UIHandlePendingElicitationRequest) (*UIElicitationResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["requestId"] = params.RequestID diff --git a/go/session.go b/go/session.go index 7b5fef697..a2e52e72c 100644 --- a/go/session.go +++ b/go/session.go @@ -588,35 +588,35 @@ func (s *Session) handleElicitationRequest(elicitCtx ElicitationContext, request result, err := handler(elicitCtx) if err != nil { // Handler failed — attempt to cancel so the request doesn't hang. - s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ + s.RPC.UI.HandlePendingElicitation(ctx, &rpc.UIHandlePendingElicitationRequest{ RequestID: requestID, Result: rpc.UIElicitationResponse{ - Action: rpc.ElicitationResponseActionCancel, + Action: rpc.UIElicitationResponseActionCancel, }, }) return } - rpcContent := make(map[string]*rpc.ElicitationFieldValue) + rpcContent := make(map[string]*rpc.UIElicitationFieldValue) for k, v := range result.Content { rpcContent[k] = toRPCContent(v) } - s.RPC.UI.HandlePendingElicitation(ctx, &rpc.HandlePendingElicitationRequest{ + s.RPC.UI.HandlePendingElicitation(ctx, &rpc.UIHandlePendingElicitationRequest{ RequestID: requestID, Result: rpc.UIElicitationResponse{ - Action: rpc.ElicitationResponseAction(result.Action), + Action: rpc.UIElicitationResponseAction(result.Action), Content: rpcContent, }, }) } -// toRPCContent converts an arbitrary value to a *rpc.ElicitationFieldValue for elicitation responses. -func toRPCContent(v any) *rpc.ElicitationFieldValue { +// toRPCContent converts an arbitrary value to a *rpc.UIElicitationFieldValue for elicitation responses. +func toRPCContent(v any) *rpc.UIElicitationFieldValue { if v == nil { return nil } - c := &rpc.ElicitationFieldValue{} + c := &rpc.UIElicitationFieldValue{} switch val := v.(type) { case bool: c.Bool = &val @@ -699,7 +699,7 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err := ui.session.assertElicitation(); err != nil { return false, err } - defaultTrue := &rpc.ElicitationFieldValue{Bool: Bool(true)} + defaultTrue := &rpc.UIElicitationFieldValue{Bool: Bool(true)} rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ Message: message, RequestedSchema: rpc.UIElicitationSchema{ @@ -716,7 +716,7 @@ func (ui *SessionUI) Confirm(ctx context.Context, message string) (bool, error) if err != nil { return false, err } - if rpcResult.Action == rpc.ElicitationResponseActionAccept { + if rpcResult.Action == rpc.UIElicitationResponseActionAccept { if c, ok := rpcResult.Content["confirmed"]; ok && c != nil && c.Bool != nil { return *c.Bool, nil } @@ -746,7 +746,7 @@ func (ui *SessionUI) Select(ctx context.Context, message string, options []strin if err != nil { return "", false, err } - if rpcResult.Action == rpc.ElicitationResponseActionAccept { + if rpcResult.Action == rpc.UIElicitationResponseActionAccept { if c, ok := rpcResult.Content["selection"]; ok && c != nil && c.String != nil { return *c.String, true, nil } @@ -781,7 +781,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio prop.Format = &format } if opts.Default != "" { - prop.Default = &rpc.ElicitationFieldValue{String: &opts.Default} + prop.Default = &rpc.UIElicitationFieldValue{String: &opts.Default} } } rpcResult, err := ui.session.RPC.UI.Elicitation(ctx, &rpc.UIElicitationRequest{ @@ -797,7 +797,7 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio if err != nil { return "", false, err } - if rpcResult.Action == rpc.ElicitationResponseActionAccept { + if rpcResult.Action == rpc.UIElicitationResponseActionAccept { if c, ok := rpcResult.Content["value"]; ok && c != nil && c.String != nil { return *c.String, true, nil } diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index 30790f023..5073b2f92 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -1086,23 +1086,23 @@ export interface CommandsHandlePendingCommandRequest { /** * The user's response: accept (submitted), decline (rejected), or cancel (dismissed) */ -export type ElicitationResponseAction = "accept" | "decline" | "cancel"; -export type ElicitationFieldValue = string | number | boolean | string[]; +export type UIElicitationResponseAction = "accept" | "decline" | "cancel"; +export type UIElicitationFieldValue = string | number | boolean | string[]; /** * The elicitation response (accept with form values, decline, or cancel) */ -export interface UiElicitationResponse { - action: ElicitationResponseAction; - content?: ElicitationResponseContent; +export interface UIElicitationResponse { + action: UIElicitationResponseAction; + content?: UIElicitationResponseContent; } /** * The form values submitted by the user (present when action is 'accept') */ -export interface ElicitationResponseContent { - [k: string]: ElicitationFieldValue; +export interface UIElicitationResponseContent { + [k: string]: UIElicitationFieldValue; } -export interface UiElicitationRequest { +export interface UIElicitationRequest { /** * Target session identifier */ @@ -1124,10 +1124,10 @@ export interface UiElicitationRequest { */ properties: { [k: string]: - | ElicitationStringEnumField - | ElicitationStringOneOfField - | ElicitationArrayEnumField - | ElicitationArrayAnyOfField + | UIElicitationStringEnumField + | UIElicitationStringOneOfField + | UIElicitationArrayEnumField + | UIElicitationArrayAnyOfField | { type: "boolean"; description?: string; @@ -1155,14 +1155,14 @@ export interface UiElicitationRequest { required?: string[]; }; } -export interface ElicitationStringEnumField { +export interface UIElicitationStringEnumField { type: "string"; description?: string; enum: string[]; enumNames?: string[]; default?: string; } -export interface ElicitationStringOneOfField { +export interface UIElicitationStringOneOfField { type: "string"; description?: string; oneOf: { @@ -1170,7 +1170,7 @@ export interface ElicitationStringOneOfField { }[]; default?: string; } -export interface ElicitationArrayEnumField { +export interface UIElicitationArrayEnumField { type: "array"; description?: string; minItems?: number; @@ -1181,7 +1181,7 @@ export interface ElicitationArrayEnumField { }; default?: string[]; } -export interface ElicitationArrayAnyOfField { +export interface UIElicitationArrayAnyOfField { type: "array"; description?: string; minItems?: number; @@ -1194,14 +1194,14 @@ export interface ElicitationArrayAnyOfField { default?: string[]; } -export interface UiElicitationResult { +export interface UIElicitationResult { /** * Whether the response was accepted. False if the request was already resolved by another client. */ success: boolean; } -export interface HandlePendingElicitationRequest { +export interface UIHandlePendingElicitationRequest { /** * Target session identifier */ @@ -1210,7 +1210,7 @@ export interface HandlePendingElicitationRequest { * The unique request ID from the elicitation.requested event */ requestId: string; - result: UiElicitationResponse; + result: UIElicitationResponse; } export interface PermissionRequestResult { @@ -1902,9 +1902,9 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.commands.handlePendingCommand", { sessionId, ...params }), }, ui: { - elicitation: async (params: Omit): Promise => + elicitation: async (params: Omit): Promise => connection.sendRequest("session.ui.elicitation", { sessionId, ...params }), - handlePendingElicitation: async (params: Omit): Promise => + handlePendingElicitation: async (params: Omit): Promise => connection.sendRequest("session.ui.handlePendingElicitation", { sessionId, ...params }), }, permissions: { diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index c5e0d8942..7900da8cb 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -1918,7 +1918,7 @@ def to_dict(self) -> dict: result["error"] = from_union([from_str, from_none], self.error) return result -class ElicitationResponseAction(Enum): +class UIElicitationResponseAction(Enum): """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" ACCEPT = "accept" @@ -1929,7 +1929,7 @@ class ElicitationResponseAction(Enum): class UIElicitationResponse: """The elicitation response (accept with form values, decline, or cancel)""" - action: ElicitationResponseAction + action: UIElicitationResponseAction """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" content: dict[str, float | bool | list[str] | str] | None = None @@ -1938,13 +1938,13 @@ class UIElicitationResponse: @staticmethod def from_dict(obj: Any) -> 'UIElicitationResponse': assert isinstance(obj, dict) - action = ElicitationResponseAction(obj.get("action")) + action = UIElicitationResponseAction(obj.get("action")) content = from_union([lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) return UIElicitationResponse(action, content) def to_dict(self) -> dict: result: dict = {} - result["action"] = to_enum(ElicitationResponseAction, self.action) + result["action"] = to_enum(UIElicitationResponseAction, self.action) if self.content is not None: result["content"] = from_union([lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) return result @@ -1956,16 +1956,16 @@ class UIElicitationSchemaPropertyStringFormat(Enum): URI = "uri" @dataclass -class ElicitationArrayAnyOfFieldItemsAnyOf: +class UIElicitationArrayAnyOfFieldItemsAnyOf: const: str title: str @staticmethod - def from_dict(obj: Any) -> 'ElicitationArrayAnyOfFieldItemsAnyOf': + def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItemsAnyOf': assert isinstance(obj, dict) const = from_str(obj.get("const")) title = from_str(obj.get("title")) - return ElicitationArrayAnyOfFieldItemsAnyOf(const, title) + return UIElicitationArrayAnyOfFieldItemsAnyOf(const, title) def to_dict(self) -> dict: result: dict = {} @@ -1977,18 +1977,18 @@ class ItemsType(Enum): STRING = "string" @dataclass -class ElicitationArrayFieldItems: +class UIElicitationArrayFieldItems: enum: list[str] | None = None type: ItemsType | None = None - any_of: list[ElicitationArrayAnyOfFieldItemsAnyOf] | None = None + any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] | None = None @staticmethod - def from_dict(obj: Any) -> 'ElicitationArrayFieldItems': + def from_dict(obj: Any) -> 'UIElicitationArrayFieldItems': assert isinstance(obj, dict) enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) type = from_union([ItemsType, from_none], obj.get("type")) - any_of = from_union([lambda x: from_list(ElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf")) - return ElicitationArrayFieldItems(enum, type, any_of) + any_of = from_union([lambda x: from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf")) + return UIElicitationArrayFieldItems(enum, type, any_of) def to_dict(self) -> dict: result: dict = {} @@ -1997,20 +1997,20 @@ def to_dict(self) -> dict: if self.type is not None: result["type"] = from_union([lambda x: to_enum(ItemsType, x), from_none], self.type) if self.any_of is not None: - result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(ElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of) + result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of) return result @dataclass -class ElicitationStringOneOfFieldOneOf: +class UIElicitationStringOneOfFieldOneOf: const: str title: str @staticmethod - def from_dict(obj: Any) -> 'ElicitationStringOneOfFieldOneOf': + def from_dict(obj: Any) -> 'UIElicitationStringOneOfFieldOneOf': assert isinstance(obj, dict) const = from_str(obj.get("const")) title = from_str(obj.get("title")) - return ElicitationStringOneOfFieldOneOf(const, title) + return UIElicitationStringOneOfFieldOneOf(const, title) def to_dict(self) -> dict: result: dict = {} @@ -2033,8 +2033,8 @@ class UIElicitationSchemaProperty: enum: list[str] | None = None enum_names: list[str] | None = None title: str | None = None - one_of: list[ElicitationStringOneOfFieldOneOf] | None = None - items: ElicitationArrayFieldItems | None = None + one_of: list[UIElicitationStringOneOfFieldOneOf] | None = None + items: UIElicitationArrayFieldItems | None = None max_items: float | None = None min_items: float | None = None format: UIElicitationSchemaPropertyStringFormat | None = None @@ -2052,8 +2052,8 @@ def from_dict(obj: Any) -> 'UIElicitationSchemaProperty': enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) enum_names = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enumNames")) title = from_union([from_str, from_none], obj.get("title")) - one_of = from_union([lambda x: from_list(ElicitationStringOneOfFieldOneOf.from_dict, x), from_none], obj.get("oneOf")) - items = from_union([ElicitationArrayFieldItems.from_dict, from_none], obj.get("items")) + one_of = from_union([lambda x: from_list(UIElicitationStringOneOfFieldOneOf.from_dict, x), from_none], obj.get("oneOf")) + items = from_union([UIElicitationArrayFieldItems.from_dict, from_none], obj.get("items")) max_items = from_union([from_float, from_none], obj.get("maxItems")) min_items = from_union([from_float, from_none], obj.get("minItems")) format = from_union([UIElicitationSchemaPropertyStringFormat, from_none], obj.get("format")) @@ -2077,9 +2077,9 @@ def to_dict(self) -> dict: if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) if self.one_of is not None: - result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(ElicitationStringOneOfFieldOneOf, x), x), from_none], self.one_of) + result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationStringOneOfFieldOneOf, x), x), from_none], self.one_of) if self.items is not None: - result["items"] = from_union([lambda x: to_class(ElicitationArrayFieldItems, x), from_none], self.items) + result["items"] = from_union([lambda x: to_class(UIElicitationArrayFieldItems, x), from_none], self.items) if self.max_items is not None: result["maxItems"] = from_union([to_float, from_none], self.max_items) if self.min_items is not None: @@ -2168,7 +2168,7 @@ def to_dict(self) -> dict: return result @dataclass -class HandlePendingElicitationRequest: +class UIHandlePendingElicitationRequest: request_id: str """The unique request ID from the elicitation.requested event""" @@ -2176,11 +2176,11 @@ class HandlePendingElicitationRequest: """The elicitation response (accept with form values, decline, or cancel)""" @staticmethod - def from_dict(obj: Any) -> 'HandlePendingElicitationRequest': + def from_dict(obj: Any) -> 'UIHandlePendingElicitationRequest': assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) result = UIElicitationResponse.from_dict(obj.get("result")) - return HandlePendingElicitationRequest(request_id, result) + return UIHandlePendingElicitationRequest(request_id, result) def to_dict(self) -> dict: result: dict = {} @@ -3415,11 +3415,11 @@ def ui_elicitation_result_from_dict(s: Any) -> UIElicitationResult: def ui_elicitation_result_to_dict(x: UIElicitationResult) -> Any: return to_class(UIElicitationResult, x) -def handle_pending_elicitation_request_from_dict(s: Any) -> HandlePendingElicitationRequest: - return HandlePendingElicitationRequest.from_dict(s) +def ui_handle_pending_elicitation_request_from_dict(s: Any) -> UIHandlePendingElicitationRequest: + return UIHandlePendingElicitationRequest.from_dict(s) -def handle_pending_elicitation_request_to_dict(x: HandlePendingElicitationRequest) -> Any: - return to_class(HandlePendingElicitationRequest, x) +def ui_handle_pending_elicitation_request_to_dict(x: UIHandlePendingElicitationRequest) -> Any: + return to_class(UIHandlePendingElicitationRequest, x) def permission_request_result_from_dict(s: Any) -> PermissionRequestResult: return PermissionRequestResult.from_dict(s) @@ -3880,7 +3880,7 @@ async def elicitation(self, params: UIElicitationRequest, *, timeout: float | No params_dict["sessionId"] = self._session_id return UIElicitationResponse.from_dict(await self._client.request("session.ui.elicitation", params_dict, **_timeout_kwargs(timeout))) - async def handle_pending_elicitation(self, params: HandlePendingElicitationRequest, *, timeout: float | None = None) -> UIElicitationResult: + async def handle_pending_elicitation(self, params: UIHandlePendingElicitationRequest, *, timeout: float | None = None) -> UIElicitationResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return UIElicitationResult.from_dict(await self._client.request("session.ui.handlePendingElicitation", params_dict, **_timeout_kwargs(timeout))) From b5ef3cac73a26d6e4fda5ac5481758959847375e Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 16:07:27 +0100 Subject: [PATCH 08/18] Renames Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- go/session_test.go | 4 ++-- python/copilot/session.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/go/session_test.go b/go/session_test.go index d247b32bf..845b2107d 100644 --- a/go/session_test.go +++ b/go/session_test.go @@ -403,7 +403,7 @@ func TestSession_Capabilities(t *testing.T) { session.dispatchEvent(SessionEvent{ Type: SessionEventTypeCapabilitiesChanged, Data: &CapabilitiesChangedData{ - UI: &CapabilitiesChangedUi{Elicitation: &elicitTrue}, + UI: &CapabilitiesChangedUI{Elicitation: &elicitTrue}, }, }) @@ -420,7 +420,7 @@ func TestSession_Capabilities(t *testing.T) { session.dispatchEvent(SessionEvent{ Type: SessionEventTypeCapabilitiesChanged, Data: &CapabilitiesChangedData{ - UI: &CapabilitiesChangedUi{Elicitation: &elicitFalse}, + UI: &CapabilitiesChangedUI{Elicitation: &elicitFalse}, }, }) diff --git a/python/copilot/session.py b/python/copilot/session.py index 4c6dd0fa1..e8d4245d1 100644 --- a/python/copilot/session.py +++ b/python/copilot/session.py @@ -24,7 +24,7 @@ from .generated.rpc import ( ClientSessionApiHandlers, CommandsHandlePendingCommandRequest, - HandlePendingElicitationRequest, + UIHandlePendingElicitationRequest, Kind, LogRequest, ModelSwitchToRequest, @@ -36,7 +36,7 @@ SessionRpc, ToolCallResult, ToolsHandlePendingToolCallRequest, - UIElicitationAction, + UIElicitationResponseAction, UIElicitationRequest, UIElicitationResponse, UIElicitationSchema, @@ -476,7 +476,7 @@ async def confirm(self, message: str) -> bool: ) ) return ( - rpc_result.action == UIElicitationAction.ACCEPT + rpc_result.action == UIElicitationResponseAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("confirmed") is True ) @@ -511,7 +511,7 @@ async def select(self, message: str, options: list[str]) -> str | None: ) ) if ( - rpc_result.action == UIElicitationAction.ACCEPT + rpc_result.action == UIElicitationResponseAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("selection") is not None ): @@ -551,7 +551,7 @@ async def input(self, message: str, options: InputOptions | None = None) -> str ) ) if ( - rpc_result.action == UIElicitationAction.ACCEPT + rpc_result.action == UIElicitationResponseAction.ACCEPT and rpc_result.content is not None and rpc_result.content.get("value") is not None ): @@ -1489,11 +1489,11 @@ async def _handle_elicitation_request( result = cast(ElicitationResult, result) action_val = result.get("action", "cancel") rpc_result = UIElicitationResponse( - action=UIElicitationAction(action_val), + action=UIElicitationResponseAction(action_val), content=result.get("content"), ) await self.rpc.ui.handle_pending_elicitation( - HandlePendingElicitationRequest( + UIHandlePendingElicitationRequest( request_id=request_id, result=rpc_result, ) @@ -1502,10 +1502,10 @@ async def _handle_elicitation_request( # Handler failed — attempt to cancel so the request doesn't hang try: await self.rpc.ui.handle_pending_elicitation( - HandlePendingElicitationRequest( + UIHandlePendingElicitationRequest( request_id=request_id, result=UIElicitationResponse( - action=UIElicitationAction.CANCEL, + action=UIElicitationResponseAction.CANCEL, ), ) ) From b5a019cca55eecc2fa83e19cf96c69f4d7c37e6a Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 16:13:47 +0100 Subject: [PATCH 09/18] Update rpc.test.ts Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- nodejs/test/e2e/rpc.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nodejs/test/e2e/rpc.test.ts b/nodejs/test/e2e/rpc.test.ts index 173d6c032..bca4e8cd7 100644 --- a/nodejs/test/e2e/rpc.test.ts +++ b/nodejs/test/e2e/rpc.test.ts @@ -112,16 +112,18 @@ describe("Session RPC", async () => { expect(initial).toBe("interactive"); // Switch to plan mode - const planResult = await session.rpc.mode.set({ mode: "plan" }); - expect(planResult).toBe("plan"); + await session.rpc.mode.set({ mode: "plan" }); // Verify mode persisted const afterPlan = await session.rpc.mode.get(); expect(afterPlan).toBe("plan"); // Switch back to interactive - const interactiveResult = await session.rpc.mode.set({ mode: "interactive" }); - expect(interactiveResult).toBe("interactive"); + await session.rpc.mode.set({ mode: "interactive" }); + + // Verify switch back + const afterInteractive = await session.rpc.mode.get(); + expect(afterInteractive).toBe("interactive"); }); it("should read, update, and delete plan", async () => { From a84f05c1f2051685324e444802ab2c1b4c722da1 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 16:28:04 +0100 Subject: [PATCH 10/18] Regen again Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 31 ++++++++++++----------------- go/rpc/generated_rpc.go | 26 ++++++++++-------------- nodejs/src/generated/rpc.ts | 25 ++++++++++------------- python/copilot/generated/rpc.py | 35 ++++++++++++--------------------- 4 files changed, 46 insertions(+), 71 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index bad821fc2..c705f8943 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -364,8 +364,8 @@ internal sealed class LogRequest public string? Url { get; set; } } -/// RPC data type for ModelCurrent operations. -public sealed class ModelCurrent +/// RPC data type for CurrentModel operations. +public sealed class CurrentModel { /// Currently active model identifier. [JsonPropertyName("modelId")] @@ -718,6 +718,7 @@ internal sealed class AgentSelectRequest } /// RPC data type for SessionAgentDeselect operations. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionAgentDeselectRequest { /// Target session identifier. @@ -832,6 +833,7 @@ internal sealed class SkillsDisableRequest } /// RPC data type for SessionSkillsReload operations. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionSkillsReloadRequest { /// Target session identifier. @@ -907,6 +909,7 @@ internal sealed class McpDisableRequest } /// RPC data type for SessionMcpReload operations. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionMcpReloadRequest { /// Target session identifier. @@ -1021,6 +1024,7 @@ internal sealed class ExtensionsDisableRequest } /// RPC data type for SessionExtensionsReload operations. +[Experimental(Diagnostics.Experimental)] internal sealed class SessionExtensionsReloadRequest { /// Target session identifier. @@ -2102,10 +2106,10 @@ internal ModelApi(JsonRpc rpc, string sessionId) } /// Calls "session.model.getCurrent". - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionModelGetCurrentRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.getCurrent", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.model.getCurrent", [request], cancellationToken); } /// Calls "session.model.switchTo". @@ -2233,6 +2237,7 @@ public async Task StartAsync(string? prompt = null, Cancellati } /// Provides session-scoped Agent APIs. +[Experimental(Diagnostics.Experimental)] public sealed class AgentApi { private readonly JsonRpc _rpc; @@ -2245,7 +2250,6 @@ internal AgentApi(JsonRpc rpc, string sessionId) } /// Calls "session.agent.list". - [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentListRequest { SessionId = _sessionId }; @@ -2253,7 +2257,6 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Calls "session.agent.getCurrent". - [Experimental(Diagnostics.Experimental)] public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentGetCurrentRequest { SessionId = _sessionId }; @@ -2261,7 +2264,6 @@ public async Task GetCurrentAsync(CancellationToken cancellationTo } /// Calls "session.agent.select". - [Experimental(Diagnostics.Experimental)] public async Task SelectAsync(string name, CancellationToken cancellationToken = default) { var request = new AgentSelectRequest { SessionId = _sessionId, Name = name }; @@ -2276,7 +2278,6 @@ public async Task DeselectAsync(CancellationToken cancellationToken = default) } /// Calls "session.agent.reload". - [Experimental(Diagnostics.Experimental)] public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentReloadRequest { SessionId = _sessionId }; @@ -2285,6 +2286,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = } /// Provides session-scoped Skills APIs. +[Experimental(Diagnostics.Experimental)] public sealed class SkillsApi { private readonly JsonRpc _rpc; @@ -2297,7 +2299,6 @@ internal SkillsApi(JsonRpc rpc, string sessionId) } /// Calls "session.skills.list". - [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionSkillsListRequest { SessionId = _sessionId }; @@ -2305,7 +2306,6 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Calls "session.skills.enable". - [Experimental(Diagnostics.Experimental)] public async Task EnableAsync(string name, CancellationToken cancellationToken = default) { var request = new SkillsEnableRequest { SessionId = _sessionId, Name = name }; @@ -2313,7 +2313,6 @@ public async Task EnableAsync(string name, CancellationToken cancellationToken = } /// Calls "session.skills.disable". - [Experimental(Diagnostics.Experimental)] public async Task DisableAsync(string name, CancellationToken cancellationToken = default) { var request = new SkillsDisableRequest { SessionId = _sessionId, Name = name }; @@ -2329,6 +2328,7 @@ public async Task ReloadAsync(CancellationToken cancellationToken = default) } /// Provides session-scoped Mcp APIs. +[Experimental(Diagnostics.Experimental)] public sealed class McpApi { private readonly JsonRpc _rpc; @@ -2341,7 +2341,6 @@ internal McpApi(JsonRpc rpc, string sessionId) } /// Calls "session.mcp.list". - [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionMcpListRequest { SessionId = _sessionId }; @@ -2349,7 +2348,6 @@ public async Task ListAsync(CancellationToken cancellationToken = } /// Calls "session.mcp.enable". - [Experimental(Diagnostics.Experimental)] public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) { var request = new McpEnableRequest { SessionId = _sessionId, ServerName = serverName }; @@ -2357,7 +2355,6 @@ public async Task EnableAsync(string serverName, CancellationToken cancellationT } /// Calls "session.mcp.disable". - [Experimental(Diagnostics.Experimental)] public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) { var request = new McpDisableRequest { SessionId = _sessionId, ServerName = serverName }; @@ -2394,6 +2391,7 @@ public async Task ListAsync(CancellationToken cancellationToken = de } /// Provides session-scoped Extensions APIs. +[Experimental(Diagnostics.Experimental)] public sealed class ExtensionsApi { private readonly JsonRpc _rpc; @@ -2406,7 +2404,6 @@ internal ExtensionsApi(JsonRpc rpc, string sessionId) } /// Calls "session.extensions.list". - [Experimental(Diagnostics.Experimental)] public async Task ListAsync(CancellationToken cancellationToken = default) { var request = new SessionExtensionsListRequest { SessionId = _sessionId }; @@ -2414,7 +2411,6 @@ public async Task ListAsync(CancellationToken cancellationToken = } /// Calls "session.extensions.enable". - [Experimental(Diagnostics.Experimental)] public async Task EnableAsync(string id, CancellationToken cancellationToken = default) { var request = new ExtensionsEnableRequest { SessionId = _sessionId, Id = id }; @@ -2422,7 +2418,6 @@ public async Task EnableAsync(string id, CancellationToken cancellationToken = d } /// Calls "session.extensions.disable". - [Experimental(Diagnostics.Experimental)] public async Task DisableAsync(string id, CancellationToken cancellationToken = default) { var request = new ExtensionsDisableRequest { SessionId = _sessionId, Id = id }; @@ -2762,6 +2757,7 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func => + getCurrent: async (): Promise => connection.sendRequest("session.model.getCurrent", { sessionId }), switchTo: async (params: Omit): Promise => connection.sendRequest("session.model.switchTo", { sessionId, ...params }), @@ -1833,43 +1837,36 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin start: async (params: Omit): Promise => connection.sendRequest("session.fleet.start", { sessionId, ...params }), }, + /** @experimental */ agent: { - /** @experimental */ list: async (): Promise => connection.sendRequest("session.agent.list", { sessionId }), - /** @experimental */ getCurrent: async (): Promise => connection.sendRequest("session.agent.getCurrent", { sessionId }), - /** @experimental */ select: async (params: Omit): Promise => connection.sendRequest("session.agent.select", { sessionId, ...params }), deselect: async (): Promise => connection.sendRequest("session.agent.deselect", { sessionId }), - /** @experimental */ reload: async (): Promise => connection.sendRequest("session.agent.reload", { sessionId }), }, + /** @experimental */ skills: { - /** @experimental */ list: async (): Promise => connection.sendRequest("session.skills.list", { sessionId }), - /** @experimental */ enable: async (params: Omit): Promise => connection.sendRequest("session.skills.enable", { sessionId, ...params }), - /** @experimental */ disable: async (params: Omit): Promise => connection.sendRequest("session.skills.disable", { sessionId, ...params }), reload: async (): Promise => connection.sendRequest("session.skills.reload", { sessionId }), }, + /** @experimental */ mcp: { - /** @experimental */ list: async (): Promise => connection.sendRequest("session.mcp.list", { sessionId }), - /** @experimental */ enable: async (params: Omit): Promise => connection.sendRequest("session.mcp.enable", { sessionId, ...params }), - /** @experimental */ disable: async (params: Omit): Promise => connection.sendRequest("session.mcp.disable", { sessionId, ...params }), reload: async (): Promise => @@ -1880,14 +1877,12 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin list: async (): Promise => connection.sendRequest("session.plugins.list", { sessionId }), }, + /** @experimental */ extensions: { - /** @experimental */ list: async (): Promise => connection.sendRequest("session.extensions.list", { sessionId }), - /** @experimental */ enable: async (params: Omit): Promise => connection.sendRequest("session.extensions.enable", { sessionId, ...params }), - /** @experimental */ disable: async (params: Omit): Promise => connection.sendRequest("session.extensions.disable", { sessionId, ...params }), reload: async (): Promise => diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 7900da8cb..dcf5a0fab 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -938,15 +938,15 @@ def to_dict(self) -> dict: return result @dataclass -class ModelCurrent: +class CurrentModel: model_id: str | None = None """Currently active model identifier""" @staticmethod - def from_dict(obj: Any) -> 'ModelCurrent': + def from_dict(obj: Any) -> 'CurrentModel': assert isinstance(obj, dict) model_id = from_union([from_str, from_none], obj.get("modelId")) - return ModelCurrent(model_id) + return CurrentModel(model_id) def to_dict(self) -> dict: result: dict = {} @@ -3205,11 +3205,11 @@ def sessions_fork_request_from_dict(s: Any) -> SessionsForkRequest: def sessions_fork_request_to_dict(x: SessionsForkRequest) -> Any: return to_class(SessionsForkRequest, x) -def model_current_from_dict(s: Any) -> ModelCurrent: - return ModelCurrent.from_dict(s) +def current_model_from_dict(s: Any) -> CurrentModel: + return CurrentModel.from_dict(s) -def model_current_to_dict(x: ModelCurrent) -> Any: - return to_class(ModelCurrent, x) +def current_model_to_dict(x: CurrentModel) -> Any: + return to_class(CurrentModel, x) def model_switch_to_result_from_dict(s: Any) -> ModelSwitchToResult: return ModelSwitchToResult.from_dict(s) @@ -3665,8 +3665,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def get_current(self, *, timeout: float | None = None) -> ModelCurrent: - return ModelCurrent.from_dict(await self._client.request("session.model.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_current(self, *, timeout: float | None = None) -> CurrentModel: + return CurrentModel.from_dict(await self._client.request("session.model.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def switch_to(self, params: ModelSwitchToRequest, *, timeout: float | None = None) -> ModelSwitchToResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} @@ -3736,21 +3736,19 @@ async def start(self, params: FleetStartRequest, *, timeout: float | None = None return FleetStartResult.from_dict(await self._client.request("session.fleet.start", params_dict, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class AgentApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> AgentList: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentList.from_dict(await self._client.request("session.agent.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def get_current(self, *, timeout: float | None = None) -> AgentCurrent: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentCurrent.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def select(self, params: AgentSelectRequest, *, timeout: float | None = None) -> AgentSelectResult: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return AgentSelectResult.from_dict(await self._client.request("session.agent.select", params_dict, **_timeout_kwargs(timeout))) @@ -3759,27 +3757,24 @@ async def deselect(self, *, timeout: float | None = None) -> None: await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) async def reload(self, *, timeout: float | None = None) -> AgentReload: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return AgentReload.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class SkillsApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> SkillList: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return SkillList.from_dict(await self._client.request("session.skills.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def enable(self, params: SkillsEnableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.skills.enable", params_dict, **_timeout_kwargs(timeout)) async def disable(self, params: SkillsDisableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.skills.disable", params_dict, **_timeout_kwargs(timeout)) @@ -3788,23 +3783,21 @@ async def reload(self, *, timeout: float | None = None) -> None: await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) +# Experimental: this API group is experimental and may change or be removed. class McpApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> MCPServerList: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return MCPServerList.from_dict(await self._client.request("session.mcp.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def enable(self, params: MCPEnableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.mcp.enable", params_dict, **_timeout_kwargs(timeout)) async def disable(self, params: MCPDisableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.mcp.disable", params_dict, **_timeout_kwargs(timeout)) @@ -3823,23 +3816,21 @@ async def list(self, *, timeout: float | None = None) -> PluginList: return PluginList.from_dict(await self._client.request("session.plugins.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. class ExtensionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id async def list(self, *, timeout: float | None = None) -> ExtensionList: - """.. warning:: This API is experimental and may change or be removed in future versions.""" return ExtensionList.from_dict(await self._client.request("session.extensions.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def enable(self, params: ExtensionsEnableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.extensions.enable", params_dict, **_timeout_kwargs(timeout)) async def disable(self, params: ExtensionsDisableRequest, *, timeout: float | None = None) -> None: - """.. warning:: This API is experimental and may change or be removed in future versions.""" params_dict = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id await self._client.request("session.extensions.disable", params_dict, **_timeout_kwargs(timeout)) From 797627fd597ff92ce9608147c1b8b0b6007650d0 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 13 Apr 2026 16:44:03 +0100 Subject: [PATCH 11/18] Yet again Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 74 ++++++++--------- go/rpc/generated_rpc.go | 90 ++++++++++----------- nodejs/src/generated/rpc.ts | 28 +++---- python/copilot/generated/rpc.py | 138 ++++++++++++++++---------------- 4 files changed, 165 insertions(+), 165 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index c705f8943..6b4bae2ba 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -239,8 +239,8 @@ public sealed class AccountQuotaSnapshot public DateTimeOffset? ResetDate { get; set; } } -/// RPC data type for AccountQuota operations. -public sealed class AccountQuota +/// RPC data type for AccountGetQuota operations. +public sealed class AccountGetQuotaResult { /// Quota snapshots keyed by type (e.g., chat, completions, premium_interactions). [JsonPropertyName("quotaSnapshots")] @@ -493,8 +493,8 @@ internal sealed class ModeSetRequest public SessionMode Mode { get; set; } } -/// RPC data type for Plan operations. -public sealed class Plan +/// RPC data type for PlanRead operations. +public sealed class PlanReadResult { /// Whether the plan file exists in the workspace. [JsonPropertyName("exists")] @@ -537,8 +537,8 @@ internal sealed class SessionPlanDeleteRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for WorkspaceFiles operations. -public sealed class WorkspaceFiles +/// RPC data type for WorkspaceListFiles operations. +public sealed class WorkspaceListFilesResult { /// Relative file paths in the workspace files directory. [JsonPropertyName("files")] @@ -645,8 +645,8 @@ internal sealed class SessionAgentListRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for AgentCurrentAgent operations. -public sealed class AgentCurrentAgent +/// RPC data type for AgentGetCurrentResultAgent operations. +public sealed class AgentGetCurrentResultAgent { /// Unique identifier of the custom agent. [JsonPropertyName("name")] @@ -661,13 +661,13 @@ public sealed class AgentCurrentAgent public string Description { get; set; } = string.Empty; } -/// RPC data type for AgentCurrent operations. +/// RPC data type for AgentGetCurrent operations. [Experimental(Diagnostics.Experimental)] -public sealed class AgentCurrent +public sealed class AgentGetCurrentResult { /// Currently selected custom agent, or null if using the default agent. [JsonPropertyName("agent")] - public AgentCurrentAgent? Agent { get; set; } + public AgentGetCurrentResultAgent? Agent { get; set; } } /// RPC data type for SessionAgentGetCurrent operations. @@ -744,7 +744,7 @@ public sealed class AgentReloadAgent /// RPC data type for AgentReload operations. [Experimental(Diagnostics.Experimental)] -public sealed class AgentReload +public sealed class AgentReloadResult { /// Reloaded custom agents. [JsonPropertyName("agents")] @@ -1266,7 +1266,7 @@ public sealed class HistoryCompactContextWindow /// RPC data type for HistoryCompact operations. [Experimental(Diagnostics.Experimental)] -public sealed class HistoryCompact +public sealed class HistoryCompactResult { /// Whether compaction completed successfully. [JsonPropertyName("success")] @@ -1388,9 +1388,9 @@ public sealed class UsageMetricsModelMetric public UsageMetricsModelMetricUsage Usage { get => field ??= new(); set; } } -/// RPC data type for UsageMetrics operations. +/// RPC data type for UsageGetMetrics operations. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetrics +public sealed class UsageGetMetricsResult { /// Total user-initiated premium request cost across all models (may be fractional due to multipliers). [JsonPropertyName("totalPremiumRequestCost")] @@ -1944,9 +1944,9 @@ internal ServerAccountApi(JsonRpc rpc) } /// Calls "account.getQuota". - public async Task GetQuotaAsync(CancellationToken cancellationToken = default) + public async Task GetQuotaAsync(CancellationToken cancellationToken = default) { - return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [], cancellationToken); } } @@ -2160,10 +2160,10 @@ internal PlanApi(JsonRpc rpc, string sessionId) } /// Calls "session.plan.read". - public async Task ReadAsync(CancellationToken cancellationToken = default) + public async Task ReadAsync(CancellationToken cancellationToken = default) { var request = new SessionPlanReadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.read", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.plan.read", [request], cancellationToken); } /// Calls "session.plan.update". @@ -2194,10 +2194,10 @@ internal WorkspaceApi(JsonRpc rpc, string sessionId) } /// Calls "session.workspace.listFiles". - public async Task ListFilesAsync(CancellationToken cancellationToken = default) + public async Task ListFilesAsync(CancellationToken cancellationToken = default) { var request = new SessionWorkspaceListFilesRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.listFiles", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.workspace.listFiles", [request], cancellationToken); } /// Calls "session.workspace.readFile". @@ -2257,10 +2257,10 @@ public async Task ListAsync(CancellationToken cancellationToken = def } /// Calls "session.agent.getCurrent". - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentGetCurrentRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.getCurrent", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.getCurrent", [request], cancellationToken); } /// Calls "session.agent.select". @@ -2278,10 +2278,10 @@ public async Task DeselectAsync(CancellationToken cancellationToken = default) } /// Calls "session.agent.reload". - public async Task ReloadAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { var request = new SessionAgentReloadRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.reload", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.agent.reload", [request], cancellationToken); } } @@ -2560,10 +2560,10 @@ internal HistoryApi(JsonRpc rpc, string sessionId) } /// Calls "session.history.compact". - public async Task CompactAsync(CancellationToken cancellationToken = default) + public async Task CompactAsync(CancellationToken cancellationToken = default) { var request = new SessionHistoryCompactRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.compact", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.compact", [request], cancellationToken); } /// Calls "session.history.truncate". @@ -2588,10 +2588,10 @@ internal UsageApi(JsonRpc rpc, string sessionId) } /// Calls "session.usage.getMetrics". - public async Task GetMetricsAsync(CancellationToken cancellationToken = default) + public async Task GetMetricsAsync(CancellationToken cancellationToken = default) { var request = new SessionUsageGetMetricsRequest { SessionId = _sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.usage.getMetrics", [request], cancellationToken); + return await CopilotClient.InvokeRpcAsync(_rpc, "session.usage.getMetrics", [request], cancellationToken); } } @@ -2744,14 +2744,14 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, Func => + getQuota: async (): Promise => connection.sendRequest("account.getQuota", {}), }, mcp: { @@ -1817,7 +1817,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.mode.set", { sessionId, ...params }), }, plan: { - read: async (): Promise => + read: async (): Promise => connection.sendRequest("session.plan.read", { sessionId }), update: async (params: Omit): Promise => connection.sendRequest("session.plan.update", { sessionId, ...params }), @@ -1825,7 +1825,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.plan.delete", { sessionId }), }, workspace: { - listFiles: async (): Promise => + listFiles: async (): Promise => connection.sendRequest("session.workspace.listFiles", { sessionId }), readFile: async (params: Omit): Promise => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }), @@ -1841,13 +1841,13 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin agent: { list: async (): Promise => connection.sendRequest("session.agent.list", { sessionId }), - getCurrent: async (): Promise => + getCurrent: async (): Promise => connection.sendRequest("session.agent.getCurrent", { sessionId }), select: async (params: Omit): Promise => connection.sendRequest("session.agent.select", { sessionId, ...params }), deselect: async (): Promise => connection.sendRequest("session.agent.deselect", { sessionId }), - reload: async (): Promise => + reload: async (): Promise => connection.sendRequest("session.agent.reload", { sessionId }), }, /** @experimental */ @@ -1916,14 +1916,14 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin }, /** @experimental */ history: { - compact: async (): Promise => + compact: async (): Promise => connection.sendRequest("session.history.compact", { sessionId }), truncate: async (params: Omit): Promise => connection.sendRequest("session.history.truncate", { sessionId, ...params }), }, /** @experimental */ usage: { - getMetrics: async (): Promise => + getMetrics: async (): Promise => connection.sendRequest("session.usage.getMetrics", { sessionId }), }, }; diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index dcf5a0fab..cafb79052 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -454,15 +454,15 @@ def to_dict(self) -> dict: return result @dataclass -class AccountQuota: +class AccountGetQuotaResult: quota_snapshots: dict[str, AccountQuotaSnapshot] """Quota snapshots keyed by type (e.g., chat, completions, premium_interactions)""" @staticmethod - def from_dict(obj: Any) -> 'AccountQuota': + def from_dict(obj: Any) -> 'AccountGetQuotaResult': assert isinstance(obj, dict) quota_snapshots = from_dict(AccountQuotaSnapshot.from_dict, obj.get("quotaSnapshots")) - return AccountQuota(quota_snapshots) + return AccountGetQuotaResult(quota_snapshots) def to_dict(self) -> dict: result: dict = {} @@ -1131,7 +1131,7 @@ def to_dict(self) -> dict: return result @dataclass -class Plan: +class PlanReadResult: exists: bool """Whether the plan file exists in the workspace""" @@ -1142,12 +1142,12 @@ class Plan: """Absolute file path of the plan file, or null if workspace is not enabled""" @staticmethod - def from_dict(obj: Any) -> 'Plan': + def from_dict(obj: Any) -> 'PlanReadResult': assert isinstance(obj, dict) exists = from_bool(obj.get("exists")) content = from_union([from_none, from_str], obj.get("content")) path = from_union([from_none, from_str], obj.get("path")) - return Plan(exists, content, path) + return PlanReadResult(exists, content, path) def to_dict(self) -> dict: result: dict = {} @@ -1173,15 +1173,15 @@ def to_dict(self) -> dict: return result @dataclass -class WorkspaceFiles: +class WorkspaceListFilesResult: files: list[str] """Relative file paths in the workspace files directory""" @staticmethod - def from_dict(obj: Any) -> 'WorkspaceFiles': + def from_dict(obj: Any) -> 'WorkspaceListFilesResult': assert isinstance(obj, dict) files = from_list(from_str, obj.get("files")) - return WorkspaceFiles(files) + return WorkspaceListFilesResult(files) def to_dict(self) -> dict: result: dict = {} @@ -1320,7 +1320,7 @@ def to_dict(self) -> dict: return result @dataclass -class AgentCurrentAgent: +class AgentGetCurrentResultAgent: description: str """Description of the agent's purpose""" @@ -1331,12 +1331,12 @@ class AgentCurrentAgent: """Unique identifier of the custom agent""" @staticmethod - def from_dict(obj: Any) -> 'AgentCurrentAgent': + def from_dict(obj: Any) -> 'AgentGetCurrentResultAgent': assert isinstance(obj, dict) description = from_str(obj.get("description")) display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - return AgentCurrentAgent(description, display_name, name) + return AgentGetCurrentResultAgent(description, display_name, name) def to_dict(self) -> dict: result: dict = {} @@ -1347,19 +1347,19 @@ def to_dict(self) -> dict: # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AgentCurrent: - agent: AgentCurrentAgent | None = None +class AgentGetCurrentResult: + agent: AgentGetCurrentResultAgent | None = None """Currently selected custom agent, or null if using the default agent""" @staticmethod - def from_dict(obj: Any) -> 'AgentCurrent': + def from_dict(obj: Any) -> 'AgentGetCurrentResult': assert isinstance(obj, dict) - agent = from_union([AgentCurrentAgent.from_dict, from_none], obj.get("agent")) - return AgentCurrent(agent) + agent = from_union([AgentGetCurrentResultAgent.from_dict, from_none], obj.get("agent")) + return AgentGetCurrentResult(agent) def to_dict(self) -> dict: result: dict = {} - result["agent"] = from_union([lambda x: to_class(AgentCurrentAgent, x), from_none], self.agent) + result["agent"] = from_union([lambda x: to_class(AgentGetCurrentResultAgent, x), from_none], self.agent) return result @dataclass @@ -1452,15 +1452,15 @@ def to_dict(self) -> dict: # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AgentReload: +class AgentReloadResult: agents: list[AgentReloadAgent] """Reloaded custom agents""" @staticmethod - def from_dict(obj: Any) -> 'AgentReload': + def from_dict(obj: Any) -> 'AgentReloadResult': assert isinstance(obj, dict) agents = from_list(AgentReloadAgent.from_dict, obj.get("agents")) - return AgentReload(agents) + return AgentReloadResult(agents) def to_dict(self) -> dict: result: dict = {} @@ -2486,7 +2486,7 @@ def to_dict(self) -> dict: # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class HistoryCompact: +class HistoryCompactResult: messages_removed: int """Number of messages removed during compaction""" @@ -2500,13 +2500,13 @@ class HistoryCompact: """Post-compaction context window usage breakdown""" @staticmethod - def from_dict(obj: Any) -> 'HistoryCompact': + def from_dict(obj: Any) -> 'HistoryCompactResult': assert isinstance(obj, dict) messages_removed = from_int(obj.get("messagesRemoved")) success = from_bool(obj.get("success")) tokens_removed = from_int(obj.get("tokensRemoved")) context_window = from_union([HistoryCompactContextWindow.from_dict, from_none], obj.get("contextWindow")) - return HistoryCompact(messages_removed, success, tokens_removed, context_window) + return HistoryCompactResult(messages_removed, success, tokens_removed, context_window) def to_dict(self) -> dict: result: dict = {} @@ -2664,7 +2664,7 @@ def to_dict(self) -> dict: # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UsageMetrics: +class UsageGetMetricsResult: code_changes: UsageMetricsCodeChanges """Aggregated code change metrics""" @@ -2694,7 +2694,7 @@ class UsageMetrics: """Currently active model identifier""" @staticmethod - def from_dict(obj: Any) -> 'UsageMetrics': + def from_dict(obj: Any) -> 'UsageGetMetricsResult': assert isinstance(obj, dict) code_changes = UsageMetricsCodeChanges.from_dict(obj.get("codeChanges")) last_call_input_tokens = from_int(obj.get("lastCallInputTokens")) @@ -2705,7 +2705,7 @@ def from_dict(obj: Any) -> 'UsageMetrics': total_premium_request_cost = from_float(obj.get("totalPremiumRequestCost")) total_user_requests = from_int(obj.get("totalUserRequests")) current_model = from_union([from_str, from_none], obj.get("currentModel")) - return UsageMetrics(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model) + return UsageGetMetricsResult(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model) def to_dict(self) -> dict: result: dict = {} @@ -3139,11 +3139,11 @@ def tools_list_request_from_dict(s: Any) -> ToolsListRequest: def tools_list_request_to_dict(x: ToolsListRequest) -> Any: return to_class(ToolsListRequest, x) -def account_quota_from_dict(s: Any) -> AccountQuota: - return AccountQuota.from_dict(s) +def account_get_quota_result_from_dict(s: Any) -> AccountGetQuotaResult: + return AccountGetQuotaResult.from_dict(s) -def account_quota_to_dict(x: AccountQuota) -> Any: - return to_class(AccountQuota, x) +def account_get_quota_result_to_dict(x: AccountGetQuotaResult) -> Any: + return to_class(AccountGetQuotaResult, x) def mcp_config_list_from_dict(s: Any) -> MCPConfigList: return MCPConfigList.from_dict(s) @@ -3235,11 +3235,11 @@ def mode_set_request_from_dict(s: Any) -> ModeSetRequest: def mode_set_request_to_dict(x: ModeSetRequest) -> Any: return to_class(ModeSetRequest, x) -def plan_from_dict(s: Any) -> Plan: - return Plan.from_dict(s) +def plan_read_result_from_dict(s: Any) -> PlanReadResult: + return PlanReadResult.from_dict(s) -def plan_to_dict(x: Plan) -> Any: - return to_class(Plan, x) +def plan_read_result_to_dict(x: PlanReadResult) -> Any: + return to_class(PlanReadResult, x) def plan_update_request_from_dict(s: Any) -> PlanUpdateRequest: return PlanUpdateRequest.from_dict(s) @@ -3247,11 +3247,11 @@ def plan_update_request_from_dict(s: Any) -> PlanUpdateRequest: def plan_update_request_to_dict(x: PlanUpdateRequest) -> Any: return to_class(PlanUpdateRequest, x) -def workspace_files_from_dict(s: Any) -> WorkspaceFiles: - return WorkspaceFiles.from_dict(s) +def workspace_list_files_result_from_dict(s: Any) -> WorkspaceListFilesResult: + return WorkspaceListFilesResult.from_dict(s) -def workspace_files_to_dict(x: WorkspaceFiles) -> Any: - return to_class(WorkspaceFiles, x) +def workspace_list_files_result_to_dict(x: WorkspaceListFilesResult) -> Any: + return to_class(WorkspaceListFilesResult, x) def workspace_read_file_result_from_dict(s: Any) -> WorkspaceReadFileResult: return WorkspaceReadFileResult.from_dict(s) @@ -3289,11 +3289,11 @@ def agent_list_from_dict(s: Any) -> AgentList: def agent_list_to_dict(x: AgentList) -> Any: return to_class(AgentList, x) -def agent_current_from_dict(s: Any) -> AgentCurrent: - return AgentCurrent.from_dict(s) +def agent_get_current_result_from_dict(s: Any) -> AgentGetCurrentResult: + return AgentGetCurrentResult.from_dict(s) -def agent_current_to_dict(x: AgentCurrent) -> Any: - return to_class(AgentCurrent, x) +def agent_get_current_result_to_dict(x: AgentGetCurrentResult) -> Any: + return to_class(AgentGetCurrentResult, x) def agent_select_result_from_dict(s: Any) -> AgentSelectResult: return AgentSelectResult.from_dict(s) @@ -3307,11 +3307,11 @@ def agent_select_request_from_dict(s: Any) -> AgentSelectRequest: def agent_select_request_to_dict(x: AgentSelectRequest) -> Any: return to_class(AgentSelectRequest, x) -def agent_reload_from_dict(s: Any) -> AgentReload: - return AgentReload.from_dict(s) +def agent_reload_result_from_dict(s: Any) -> AgentReloadResult: + return AgentReloadResult.from_dict(s) -def agent_reload_to_dict(x: AgentReload) -> Any: - return to_class(AgentReload, x) +def agent_reload_result_to_dict(x: AgentReloadResult) -> Any: + return to_class(AgentReloadResult, x) def skill_list_from_dict(s: Any) -> SkillList: return SkillList.from_dict(s) @@ -3469,11 +3469,11 @@ def shell_kill_request_from_dict(s: Any) -> ShellKillRequest: def shell_kill_request_to_dict(x: ShellKillRequest) -> Any: return to_class(ShellKillRequest, x) -def history_compact_from_dict(s: Any) -> HistoryCompact: - return HistoryCompact.from_dict(s) +def history_compact_result_from_dict(s: Any) -> HistoryCompactResult: + return HistoryCompactResult.from_dict(s) -def history_compact_to_dict(x: HistoryCompact) -> Any: - return to_class(HistoryCompact, x) +def history_compact_result_to_dict(x: HistoryCompactResult) -> Any: + return to_class(HistoryCompactResult, x) def history_truncate_result_from_dict(s: Any) -> HistoryTruncateResult: return HistoryTruncateResult.from_dict(s) @@ -3487,11 +3487,11 @@ def history_truncate_request_from_dict(s: Any) -> HistoryTruncateRequest: def history_truncate_request_to_dict(x: HistoryTruncateRequest) -> Any: return to_class(HistoryTruncateRequest, x) -def usage_metrics_from_dict(s: Any) -> UsageMetrics: - return UsageMetrics.from_dict(s) +def usage_get_metrics_result_from_dict(s: Any) -> UsageGetMetricsResult: + return UsageGetMetricsResult.from_dict(s) -def usage_metrics_to_dict(x: UsageMetrics) -> Any: - return to_class(UsageMetrics, x) +def usage_get_metrics_result_to_dict(x: UsageGetMetricsResult) -> Any: + return to_class(UsageGetMetricsResult, x) def session_fs_read_file_result_from_dict(s: Any) -> SessionFSReadFileResult: return SessionFSReadFileResult.from_dict(s) @@ -3612,8 +3612,8 @@ class ServerAccountApi: def __init__(self, client: "JsonRpcClient"): self._client = client - async def get_quota(self, *, timeout: float | None = None) -> AccountQuota: - return AccountQuota.from_dict(await self._client.request("account.getQuota", {}, **_timeout_kwargs(timeout))) + async def get_quota(self, *, timeout: float | None = None) -> AccountGetQuotaResult: + return AccountGetQuotaResult.from_dict(await self._client.request("account.getQuota", {}, **_timeout_kwargs(timeout))) class ServerMcpApi: @@ -3693,8 +3693,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def read(self, *, timeout: float | None = None) -> Plan: - return Plan.from_dict(await self._client.request("session.plan.read", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def read(self, *, timeout: float | None = None) -> PlanReadResult: + return PlanReadResult.from_dict(await self._client.request("session.plan.read", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def update(self, params: PlanUpdateRequest, *, timeout: float | None = None) -> None: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} @@ -3710,8 +3710,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def list_files(self, *, timeout: float | None = None) -> WorkspaceFiles: - return WorkspaceFiles.from_dict(await self._client.request("session.workspace.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def list_files(self, *, timeout: float | None = None) -> WorkspaceListFilesResult: + return WorkspaceListFilesResult.from_dict(await self._client.request("session.workspace.listFiles", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def read_file(self, params: WorkspaceReadFileRequest, *, timeout: float | None = None) -> WorkspaceReadFileResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} @@ -3745,8 +3745,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): async def list(self, *, timeout: float | None = None) -> AgentList: return AgentList.from_dict(await self._client.request("session.agent.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) - async def get_current(self, *, timeout: float | None = None) -> AgentCurrent: - return AgentCurrent.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_current(self, *, timeout: float | None = None) -> AgentGetCurrentResult: + return AgentGetCurrentResult.from_dict(await self._client.request("session.agent.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def select(self, params: AgentSelectRequest, *, timeout: float | None = None) -> AgentSelectResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} @@ -3756,8 +3756,8 @@ async def select(self, params: AgentSelectRequest, *, timeout: float | None = No async def deselect(self, *, timeout: float | None = None) -> None: await self._client.request("session.agent.deselect", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) - async def reload(self, *, timeout: float | None = None) -> AgentReload: - return AgentReload.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def reload(self, *, timeout: float | None = None) -> AgentReloadResult: + return AgentReloadResult.from_dict(await self._client.request("session.agent.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) # Experimental: this API group is experimental and may change or be removed. @@ -3910,8 +3910,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def compact(self, *, timeout: float | None = None) -> HistoryCompact: - return HistoryCompact.from_dict(await self._client.request("session.history.compact", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def compact(self, *, timeout: float | None = None) -> HistoryCompactResult: + return HistoryCompactResult.from_dict(await self._client.request("session.history.compact", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def truncate(self, params: HistoryTruncateRequest, *, timeout: float | None = None) -> HistoryTruncateResult: params_dict = {k: v for k, v in params.to_dict().items() if v is not None} @@ -3925,8 +3925,8 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id - async def get_metrics(self, *, timeout: float | None = None) -> UsageMetrics: - return UsageMetrics.from_dict(await self._client.request("session.usage.getMetrics", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_metrics(self, *, timeout: float | None = None) -> UsageGetMetricsResult: + return UsageGetMetricsResult.from_dict(await self._client.request("session.usage.getMetrics", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) class SessionRpc: From 8808493b79ebe6f5999bf83984a041529cb64580 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 11:00:15 +0100 Subject: [PATCH 12/18] Update runtime Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/SessionEvents.cs | 3 ++ nodejs/package-lock.json | 56 +++++++++++++-------------- nodejs/package.json | 2 +- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 1ae47f974..7eaf54b9c 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -2953,6 +2953,7 @@ public partial class UserMessageAttachmentBlob : UserMessageAttachment public override string Type => "blob"; /// Base64-encoded content. + [Base64String] [JsonPropertyName("data")] public required string Data { get; set; } @@ -3101,6 +3102,7 @@ public partial class ToolExecutionCompleteContentImage : ToolExecutionCompleteCo public override string Type => "image"; /// Base64-encoded image data. + [Base64String] [JsonPropertyName("data")] public required string Data { get; set; } @@ -3118,6 +3120,7 @@ public partial class ToolExecutionCompleteContentAudio : ToolExecutionCompleteCo public override string Type => "audio"; /// Base64-encoded audio data. + [Base64String] [JsonPropertyName("data")] public required string Data { get; set; } diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 55c3a4f24..cc4407bbb 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.22", + "@github/copilot": "^1.0.26-0", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, @@ -663,26 +663,26 @@ } }, "node_modules/@github/copilot": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.22.tgz", - "integrity": "sha512-BR9oTJ1tQ51RV81xcxmlZe0zB3Tf8i/vFsKSTm2f5wRLJgtuVl2LgaFStoI/peTFcmgtZbhrqsnWTu5GkEPK5Q==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.26-0.tgz", + "integrity": "sha512-MHeddlLZCi5OFeuzKRtj7kmJVm1o/teNwgrL5/FHU9x0H6VioG+KGlY6gd1H/cTJ763dtYQyACMPYFUNVVY52g==", "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.22", - "@github/copilot-darwin-x64": "1.0.22", - "@github/copilot-linux-arm64": "1.0.22", - "@github/copilot-linux-x64": "1.0.22", - "@github/copilot-win32-arm64": "1.0.22", - "@github/copilot-win32-x64": "1.0.22" + "@github/copilot-darwin-arm64": "1.0.26-0", + "@github/copilot-darwin-x64": "1.0.26-0", + "@github/copilot-linux-arm64": "1.0.26-0", + "@github/copilot-linux-x64": "1.0.26-0", + "@github/copilot-win32-arm64": "1.0.26-0", + "@github/copilot-win32-x64": "1.0.26-0" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.22.tgz", - "integrity": "sha512-cK42uX+oz46Cjsb7z+rdPw+DIGczfVSFWlc1WDcdVlwBW4cEfV0pzFXExpN1r1z179TFgAaVMbhkgLqhOZ/PeQ==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.26-0.tgz", + "integrity": "sha512-C1GP4qrKjCjPoKr485o0IbcP3n1q/4LxKwAhpga0V+9ZHlvggZ58YB9AaUFySJ+Alpu1vBlw/FFpD9amroasvw==", "cpu": [ "arm64" ], @@ -696,9 +696,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.22.tgz", - "integrity": "sha512-Pmw0ipF+yeLbP6JctsEoMS2LUCpVdC2r557BnCoe48BN8lO8i9JLnkpuDDrJ1AZuCk1VjnujFKEQywOOdfVlpA==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.26-0.tgz", + "integrity": "sha512-A/HSuoCe8i5+yc5yCi4ZMi6PQfOOExA0wwpN13zFKwmqDwdNdogb4/wX42DoGr7JwuOGhZSzXCEZirt/lqqxjQ==", "cpu": [ "x64" ], @@ -712,9 +712,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.22.tgz", - "integrity": "sha512-WVgG67VmZgHoD7GMlkTxEVe1qK8k9Ek9A02/Da7obpsDdtBInt3nJTwBEgm4cNDM4XaenQH17/jmwVtTwXB6lw==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.26-0.tgz", + "integrity": "sha512-goMPZkMi5dCqA1JHbgsxaUKOmtZ6juBAeUfVomtKmdKee1KC74TFXlEuP8qJMGkeug2yivPOptAfQQXSyJJnHw==", "cpu": [ "arm64" ], @@ -728,9 +728,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.22.tgz", - "integrity": "sha512-XRkHVFmdC7FMrczXOdPjbNKiknMr13asKtwJoErJO/Xdy4cmzKQHSvNsBk8VNrr7oyWrUcB1F6mbIxb2LFxPOw==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.26-0.tgz", + "integrity": "sha512-oK6uQ0Q0ZUO9IM3B+KJb9wyRHG5ZGP5qoTOOTN7JcC+p8ZveNSGCAHUAtzLSflUREJUFYfRZauUKcfV31/Y2LA==", "cpu": [ "x64" ], @@ -744,9 +744,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.22.tgz", - "integrity": "sha512-Ao6gv1f2ZV+HVlkB1MV7YFdCuaB3NcFCnNu0a6/WLl2ypsfP1vWosPPkIB32jQJeBkT9ku3exOZLRj+XC0P3Mg==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.26-0.tgz", + "integrity": "sha512-VXwm8xryO3cUHydVkzmSzb0M3WonwGDHCcgwI2GGS2YkHB9VjmRbdpVeLYeDB5EzmyZLSd7Nr4+i2X0gsU93ow==", "cpu": [ "arm64" ], @@ -760,9 +760,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.22.tgz", - "integrity": "sha512-EppcL+3TpxC+X/eQEIYtkN0PaA3/cvtI9UJqldLIkKDPXNYk/0mw877Ru9ypRcBWBWokDN6iKIWk5IxYH+JIvg==", + "version": "1.0.26-0", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.26-0.tgz", + "integrity": "sha512-+4IFUZbYSg5jxchEFdgVEgSDJzDE/P3nRDtEBcIhpYlVb7/zAw2JCkCJr+i4Aruo4zysJnEybL0wM3TpcWTt/g==", "cpu": [ "x64" ], diff --git a/nodejs/package.json b/nodejs/package.json index 6a0ef9567..f4a3a2188 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -56,7 +56,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@github/copilot": "^1.0.22", + "@github/copilot": "^1.0.26-0", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, From ef219e764365ef9ef904189f9f2705d7fd6b0b36 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 11:11:37 +0100 Subject: [PATCH 13/18] Fix Go and Python for consistent Result suffix types - Go: Update session_fs_test.go handler signatures to return (*Result, error) for WriteFile, AppendFile, Mkdir, Rm, Rename (previously just error) - Go: Fix Stat field types (int64, time.Time) and Timestamp format verb - Go: Remove void-result assertions on Mode.Set - Python: Fix import sort order in session.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/internal/e2e/rpc_test.go | 12 +++------ go/internal/e2e/session_fs_test.go | 43 ++++++++++++++++-------------- python/copilot/session.py | 4 +-- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/go/internal/e2e/rpc_test.go b/go/internal/e2e/rpc_test.go index d5c7569a8..5a79a7509 100644 --- a/go/internal/e2e/rpc_test.go +++ b/go/internal/e2e/rpc_test.go @@ -36,7 +36,7 @@ func TestRpc(t *testing.T) { } if result.Timestamp < 0 { - t.Errorf("Expected timestamp >= 0, got %f", result.Timestamp) + t.Errorf("Expected timestamp >= 0, got %d", result.Timestamp) } if err := client.Stop(); err != nil { @@ -223,13 +223,10 @@ func TestSessionRpc(t *testing.T) { } // Switch to plan mode - planResult, err := session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModePlan}) + _, err = session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModePlan}) if err != nil { t.Fatalf("Failed to set mode to plan: %v", err) } - if *planResult != rpc.SessionModePlan { - t.Errorf("Expected mode 'plan', got %q", *planResult) - } // Verify mode persisted afterPlan, err := session.RPC.Mode.Get(t.Context()) @@ -241,13 +238,10 @@ func TestSessionRpc(t *testing.T) { } // Switch back to interactive - interactiveResult, err := session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModeInteractive}) + _, err = session.RPC.Mode.Set(t.Context(), &rpc.ModeSetRequest{Mode: rpc.SessionModeInteractive}) if err != nil { t.Fatalf("Failed to set mode to interactive: %v", err) } - if *interactiveResult != rpc.SessionModeInteractive { - t.Errorf("Expected mode 'interactive', got %q", *interactiveResult) - } }) t.Run("should read, update, and delete plan", func(t *testing.T) { diff --git a/go/internal/e2e/session_fs_test.go b/go/internal/e2e/session_fs_test.go index be52c49dc..7fba219f7 100644 --- a/go/internal/e2e/session_fs_test.go +++ b/go/internal/e2e/session_fs_test.go @@ -266,22 +266,22 @@ func (h *testSessionFsHandler) ReadFile(request *rpc.SessionFSReadFileRequest) ( return &rpc.SessionFSReadFileResult{Content: string(content)}, nil } -func (h *testSessionFsHandler) WriteFile(request *rpc.SessionFSWriteFileRequest) error { +func (h *testSessionFsHandler) WriteFile(request *rpc.SessionFSWriteFileRequest) (*rpc.SessionFSWriteFileResult, error) { path := providerPath(h.root, h.sessionID, request.Path) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return err + return nil, err } mode := os.FileMode(0o666) if request.Mode != nil { mode = os.FileMode(uint32(*request.Mode)) } - return os.WriteFile(path, []byte(request.Content), mode) + return &rpc.SessionFSWriteFileResult{}, os.WriteFile(path, []byte(request.Content), mode) } -func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileRequest) error { +func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileRequest) (*rpc.SessionFSAppendFileResult, error) { path := providerPath(h.root, h.sessionID, request.Path) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return err + return nil, err } mode := os.FileMode(0o666) if request.Mode != nil { @@ -289,11 +289,14 @@ func (h *testSessionFsHandler) AppendFile(request *rpc.SessionFSAppendFileReques } f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, mode) if err != nil { - return err + return nil, err } defer f.Close() _, err = f.WriteString(request.Content) - return err + if err != nil { + return nil, err + } + return &rpc.SessionFSAppendFileResult{}, nil } func (h *testSessionFsHandler) Exists(request *rpc.SessionFSExistsRequest) (*rpc.SessionFSExistsResult, error) { @@ -312,26 +315,26 @@ func (h *testSessionFsHandler) Stat(request *rpc.SessionFSStatRequest) (*rpc.Ses if err != nil { return nil, err } - ts := info.ModTime().UTC().Format(time.RFC3339) + ts := info.ModTime().UTC() return &rpc.SessionFSStatResult{ IsFile: !info.IsDir(), IsDirectory: info.IsDir(), - Size: float64(info.Size()), + Size: info.Size(), Mtime: ts, Birthtime: ts, }, nil } -func (h *testSessionFsHandler) Mkdir(request *rpc.SessionFSMkdirRequest) error { +func (h *testSessionFsHandler) Mkdir(request *rpc.SessionFSMkdirRequest) (*rpc.SessionFSMkdirResult, error) { path := providerPath(h.root, h.sessionID, request.Path) mode := os.FileMode(0o777) if request.Mode != nil { mode = os.FileMode(uint32(*request.Mode)) } if request.Recursive != nil && *request.Recursive { - return os.MkdirAll(path, mode) + return &rpc.SessionFSMkdirResult{}, os.MkdirAll(path, mode) } - return os.Mkdir(path, mode) + return &rpc.SessionFSMkdirResult{}, os.Mkdir(path, mode) } func (h *testSessionFsHandler) Readdir(request *rpc.SessionFSReaddirRequest) (*rpc.SessionFSReaddirResult, error) { @@ -365,28 +368,28 @@ func (h *testSessionFsHandler) ReaddirWithTypes(request *rpc.SessionFSReaddirWit return &rpc.SessionFSReaddirWithTypesResult{Entries: result}, nil } -func (h *testSessionFsHandler) Rm(request *rpc.SessionFSRmRequest) error { +func (h *testSessionFsHandler) Rm(request *rpc.SessionFSRmRequest) (*rpc.SessionFSRmResult, error) { path := providerPath(h.root, h.sessionID, request.Path) if request.Recursive != nil && *request.Recursive { err := os.RemoveAll(path) if err != nil && request.Force != nil && *request.Force && os.IsNotExist(err) { - return nil + return &rpc.SessionFSRmResult{}, nil } - return err + return &rpc.SessionFSRmResult{}, err } err := os.Remove(path) if err != nil && request.Force != nil && *request.Force && os.IsNotExist(err) { - return nil + return &rpc.SessionFSRmResult{}, nil } - return err + return &rpc.SessionFSRmResult{}, err } -func (h *testSessionFsHandler) Rename(request *rpc.SessionFSRenameRequest) error { +func (h *testSessionFsHandler) Rename(request *rpc.SessionFSRenameRequest) (*rpc.SessionFSRenameResult, error) { dest := providerPath(h.root, h.sessionID, request.Dest) if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { - return err + return nil, err } - return os.Rename( + return &rpc.SessionFSRenameResult{}, os.Rename( providerPath(h.root, h.sessionID, request.Src), dest, ) diff --git a/python/copilot/session.py b/python/copilot/session.py index e8d4245d1..5edbe924b 100644 --- a/python/copilot/session.py +++ b/python/copilot/session.py @@ -24,7 +24,6 @@ from .generated.rpc import ( ClientSessionApiHandlers, CommandsHandlePendingCommandRequest, - UIHandlePendingElicitationRequest, Kind, LogRequest, ModelSwitchToRequest, @@ -36,12 +35,13 @@ SessionRpc, ToolCallResult, ToolsHandlePendingToolCallRequest, - UIElicitationResponseAction, UIElicitationRequest, UIElicitationResponse, + UIElicitationResponseAction, UIElicitationSchema, UIElicitationSchemaProperty, UIElicitationSchemaPropertyNumberType, + UIHandlePendingElicitationRequest, ) from .generated.rpc import ModelCapabilitiesOverride as _RpcModelCapabilitiesOverride from .generated.session_events import ( From 268dae17098f232badfcb43c383abe6e84c3c022 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 11:20:15 +0100 Subject: [PATCH 14/18] Fix Python test failures - Mode.set() now returns None (void) - remove result assertions - ModelSupports.vision is optional in the schema - default to False Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/copilot/client.py | 6 ++---- python/e2e/test_rpc.py | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/python/copilot/client.py b/python/copilot/client.py index 17071e502..403732fc5 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -360,15 +360,13 @@ def to_dict(self) -> dict: class ModelSupports: """Model support flags""" - vision: bool + vision: bool = False reasoning_effort: bool = False # Whether this model supports reasoning effort @staticmethod def from_dict(obj: Any) -> ModelSupports: assert isinstance(obj, dict) - vision = obj.get("vision") - if vision is None: - raise ValueError("Missing required field 'vision' in ModelSupports") + vision = obj.get("vision", False) reasoning_effort = obj.get("reasoningEffort", False) return ModelSupports(vision=bool(vision), reasoning_effort=bool(reasoning_effort)) diff --git a/python/e2e/test_rpc.py b/python/e2e/test_rpc.py index a7c5ff321..f4f5542fc 100644 --- a/python/e2e/test_rpc.py +++ b/python/e2e/test_rpc.py @@ -129,18 +129,16 @@ async def test_get_and_set_session_mode(self): assert initial == SessionMode.INTERACTIVE # Switch to plan mode - plan_result = await session.rpc.mode.set(ModeSetRequest(mode=SessionMode.PLAN)) - assert plan_result == SessionMode.PLAN + await session.rpc.mode.set(ModeSetRequest(mode=SessionMode.PLAN)) # Verify mode persisted after_plan = await session.rpc.mode.get() assert after_plan == SessionMode.PLAN # Switch back to interactive - interactive_result = await session.rpc.mode.set( + await session.rpc.mode.set( ModeSetRequest(mode=SessionMode.INTERACTIVE) ) - assert interactive_result == SessionMode.INTERACTIVE await session.disconnect() await client.stop() From 19d5a39e0f863164f2e564f85822522bbb2d6098 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 11:23:47 +0100 Subject: [PATCH 15/18] Fix Python formatting in test_rpc.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/e2e/test_rpc.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/e2e/test_rpc.py b/python/e2e/test_rpc.py index f4f5542fc..0d9f9a4eb 100644 --- a/python/e2e/test_rpc.py +++ b/python/e2e/test_rpc.py @@ -136,9 +136,7 @@ async def test_get_and_set_session_mode(self): assert after_plan == SessionMode.PLAN # Switch back to interactive - await session.rpc.mode.set( - ModeSetRequest(mode=SessionMode.INTERACTIVE) - ) + await session.rpc.mode.set(ModeSetRequest(mode=SessionMode.INTERACTIVE)) await session.disconnect() await client.stop() From ca0f563957909690de5ff411af3557f60bd26b32 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 12:04:56 +0100 Subject: [PATCH 16/18] Make ModelCapabilities.from_dict defensive for missing fields The runtime may return models (e.g. embedding models) where 'limits' or 'supports' are absent. Default to empty objects instead of raising ValueError, matching the lenient behavior in Go/C#/TypeScript SDKs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/copilot/client.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/python/copilot/client.py b/python/copilot/client.py index 403732fc5..c47acdf14 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -389,13 +389,8 @@ def from_dict(obj: Any) -> ModelCapabilities: assert isinstance(obj, dict) supports_dict = obj.get("supports") limits_dict = obj.get("limits") - if supports_dict is None or limits_dict is None: - raise ValueError( - f"Missing required fields in ModelCapabilities: supports={supports_dict}, " - f"limits={limits_dict}" - ) - supports = ModelSupports.from_dict(supports_dict) - limits = ModelLimits.from_dict(limits_dict) + supports = ModelSupports.from_dict(supports_dict) if supports_dict else ModelSupports() + limits = ModelLimits.from_dict(limits_dict) if limits_dict else ModelLimits() return ModelCapabilities(supports=supports, limits=limits) def to_dict(self) -> dict: From cd71ba14c87c87f485fc4aedaf00af931fa83a21 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 12:05:23 +0100 Subject: [PATCH 17/18] Workaround: patch model capabilities in Python models.list deserializer TODO: Remove once the runtime schema correctly marks limits/supports and max_context_window_tokens as optional in ModelCapabilities. The generated Python deserializer (from quicktype) uses strict assert- based type checks that crash on null/missing fields. Go, C#, and TS deserializers silently zero-default these. This adds a targeted patch to models.list that supplies missing defaults before deserialization. Files to update when removing this workaround: - scripts/codegen/python.ts (remove _patch_model_capabilities helper and the string replacement logic) - python/copilot/generated/rpc.py (will be regenerated automatically) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/copilot/generated/rpc.py | 23 +++++++++++++++++++++- scripts/codegen/python.ts | 35 ++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index cafb79052..b24f74e51 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -3590,13 +3590,34 @@ def _timeout_kwargs(timeout: float | None) -> dict: return {"timeout": timeout} return {} +def _patch_model_capabilities(data: dict) -> dict: + """Ensure model capabilities have required fields. + + TODO: Remove once the runtime schema correctly marks these fields as optional. + Some models (e.g. embedding models) may omit 'limits' or 'supports' in their + capabilities, or omit 'max_context_window_tokens' within limits. The generated + deserializer requires these fields, so we supply defaults here. + """ + for model in data.get("models", []): + caps = model.get("capabilities") + if caps is None: + model["capabilities"] = {"supports": {}, "limits": {"max_context_window_tokens": 0}} + continue + if "supports" not in caps: + caps["supports"] = {} + if "limits" not in caps: + caps["limits"] = {"max_context_window_tokens": 0} + elif "max_context_window_tokens" not in caps["limits"]: + caps["limits"]["max_context_window_tokens"] = 0 + return data + class ServerModelsApi: def __init__(self, client: "JsonRpcClient"): self._client = client async def list(self, *, timeout: float | None = None) -> ModelList: - return ModelList.from_dict(await self._client.request("models.list", {}, **_timeout_kwargs(timeout))) + return ModelList.from_dict(_patch_model_capabilities(await self._client.request("models.list", {}, **_timeout_kwargs(timeout)))) class ServerToolsApi: diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index 82a08cae0..f22a83ff9 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -400,6 +400,27 @@ def _timeout_kwargs(timeout: float | None) -> dict: return {"timeout": timeout} return {} +def _patch_model_capabilities(data: dict) -> dict: + """Ensure model capabilities have required fields. + + TODO: Remove once the runtime schema correctly marks these fields as optional. + Some models (e.g. embedding models) may omit 'limits' or 'supports' in their + capabilities, or omit 'max_context_window_tokens' within limits. The generated + deserializer requires these fields, so we supply defaults here. + """ + for model in data.get("models", []): + caps = model.get("capabilities") + if caps is None: + model["capabilities"] = {"supports": {}, "limits": {"max_context_window_tokens": 0}} + continue + if "supports" not in caps: + caps["supports"] = {} + if "limits" not in caps: + caps["limits"] = {"max_context_window_tokens": 0} + elif "max_context_window_tokens" not in caps["limits"]: + caps["limits"]["max_context_window_tokens"] = 0 + return data + `); // Emit RPC wrapper classes @@ -413,7 +434,19 @@ def _timeout_kwargs(timeout: float | None) -> dict: emitClientSessionApiRegistration(lines, schema.clientSession, resolveType); } - const outPath = await writeGeneratedFile("python/copilot/generated/rpc.py", lines.join("\n")); + // Patch models.list to normalize capabilities before deserialization + let finalCode = lines.join("\n"); + finalCode = finalCode.replace( + `ModelList.from_dict(await self._client.request("models.list"`, + `ModelList.from_dict(_patch_model_capabilities(await self._client.request("models.list"`, + ); + // Close the extra paren opened by _patch_model_capabilities( + finalCode = finalCode.replace( + /(_patch_model_capabilities\(await self\._client\.request\("models\.list",\s*\{[^)]*\)[^)]*\))/, + "$1)", + ); + + const outPath = await writeGeneratedFile("python/copilot/generated/rpc.py", finalCode); console.log(` ✓ ${outPath}`); } From d634f64dea32378abc5da45233b5590316ee85a5 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 14 Apr 2026 12:48:50 +0100 Subject: [PATCH 18/18] Don't dedupe enums structurally for C# (can't totally fix for Python/Go until we remove Quicktype) Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 21 ++++++++++- dotnet/src/Generated/SessionEvents.cs | 54 +++++++++++++++++++++++++-- go/generated_session_events.go | 34 +++++++++++++++-- scripts/codegen/csharp.ts | 12 +++--- scripts/codegen/go.ts | 12 +++--- 5 files changed, 113 insertions(+), 20 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 6b4bae2ba..0bea6e8db 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -855,7 +855,7 @@ public sealed class McpServer /// Configuration source: user, workspace, plugin, or builtin. [JsonPropertyName("source")] - public DiscoveredMcpServerSource? Source { get; set; } + public McpServerSource? Source { get; set; } /// Error message if the server failed to connect. [JsonPropertyName("error")] @@ -1779,6 +1779,25 @@ public enum McpServerStatus } +/// Configuration source: user, workspace, plugin, or builtin. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum McpServerSource +{ + /// The user variant. + [JsonStringEnumMemberName("user")] + User, + /// The workspace variant. + [JsonStringEnumMemberName("workspace")] + Workspace, + /// The plugin variant. + [JsonStringEnumMemberName("plugin")] + Plugin, + /// The builtin variant. + [JsonStringEnumMemberName("builtin")] + Builtin, +} + + /// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/). [JsonConverter(typeof(JsonStringEnumConverter))] public enum ExtensionSource diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 7eaf54b9c..a0dbf3c28 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -1486,7 +1486,7 @@ public partial class SessionContextChangedData /// Hosting platform type of the repository (github or ado). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("hostType")] - public StartContextHostType? HostType { get; set; } + public ContextChangedHostType? HostType { get; set; } /// Current git branch name. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2658,7 +2658,7 @@ public partial class SessionMcpServerStatusChangedData /// New connection status: connected, failed, needs-auth, pending, disabled, or not_configured. [JsonPropertyName("status")] - public required McpServersLoadedServerStatus Status { get; set; } + public required McpServerStatusChangedStatus Status { get; set; } } /// Event payload for . @@ -2729,7 +2729,7 @@ public partial class ResumeContext /// Hosting platform type of the repository (github or ado). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("hostType")] - public StartContextHostType? HostType { get; set; } + public ResumeContextHostType? HostType { get; set; } /// Current git branch name. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3876,6 +3876,18 @@ public enum StartContextHostType Ado, } +/// Hosting platform type of the repository (github or ado). +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ResumeContextHostType +{ + /// The github variant. + [JsonStringEnumMemberName("github")] + Github, + /// The ado variant. + [JsonStringEnumMemberName("ado")] + Ado, +} + /// The type of operation performed on the plan file. [JsonConverter(typeof(JsonStringEnumConverter))] public enum PlanChangedOperation @@ -3927,6 +3939,18 @@ public enum ShutdownType Error, } +/// Hosting platform type of the repository (github or ado). +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ContextChangedHostType +{ + /// The github variant. + [JsonStringEnumMemberName("github")] + Github, + /// The ado variant. + [JsonStringEnumMemberName("ado")] + Ado, +} + /// Type of GitHub reference. [JsonConverter(typeof(JsonStringEnumConverter))] public enum UserMessageAttachmentGithubReferenceType @@ -4107,6 +4131,30 @@ public enum McpServersLoadedServerStatus NotConfigured, } +/// New connection status: connected, failed, needs-auth, pending, disabled, or not_configured. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum McpServerStatusChangedStatus +{ + /// The connected variant. + [JsonStringEnumMemberName("connected")] + Connected, + /// The failed variant. + [JsonStringEnumMemberName("failed")] + Failed, + /// The needs-auth variant. + [JsonStringEnumMemberName("needs-auth")] + NeedsAuth, + /// The pending variant. + [JsonStringEnumMemberName("pending")] + Pending, + /// The disabled variant. + [JsonStringEnumMemberName("disabled")] + Disabled, + /// The not_configured variant. + [JsonStringEnumMemberName("not_configured")] + NotConfigured, +} + /// Discovery source. [JsonConverter(typeof(JsonStringEnumConverter))] public enum ExtensionsLoadedExtensionSource diff --git a/go/generated_session_events.go b/go/generated_session_events.go index b2a2d7248..01a6a0811 100644 --- a/go/generated_session_events.go +++ b/go/generated_session_events.go @@ -865,7 +865,7 @@ type SessionContextChangedData struct { // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) Repository *string `json:"repository,omitempty"` // Hosting platform type of the repository (github or ado) - HostType *StartContextHostType `json:"hostType,omitempty"` + HostType *ContextChangedHostType `json:"hostType,omitempty"` // Current git branch name Branch *string `json:"branch,omitempty"` // Head commit of current git branch at session start time @@ -1618,7 +1618,7 @@ type SessionMcpServerStatusChangedData struct { // Name of the MCP server whose status changed ServerName string `json:"serverName"` // New connection status: connected, failed, needs-auth, pending, disabled, or not_configured - Status McpServersLoadedServerStatus `json:"status"` + Status McpServerStatusChangedStatus `json:"status"` } func (*SessionMcpServerStatusChangedData) sessionEventData() {} @@ -1658,7 +1658,7 @@ type ResumeContext struct { // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) Repository *string `json:"repository,omitempty"` // Hosting platform type of the repository (github or ado) - HostType *StartContextHostType `json:"hostType,omitempty"` + HostType *ResumeContextHostType `json:"hostType,omitempty"` // Current git branch name Branch *string `json:"branch,omitempty"` // Head commit of current git branch at session start time @@ -2116,6 +2116,14 @@ const ( StartContextHostTypeAdo StartContextHostType = "ado" ) +// Hosting platform type of the repository (github or ado) +type ResumeContextHostType string + +const ( + ResumeContextHostTypeGithub ResumeContextHostType = "github" + ResumeContextHostTypeAdo ResumeContextHostType = "ado" +) + // The type of operation performed on the plan file type PlanChangedOperation string @@ -2149,6 +2157,14 @@ const ( ShutdownTypeError ShutdownType = "error" ) +// Hosting platform type of the repository (github or ado) +type ContextChangedHostType string + +const ( + ContextChangedHostTypeGithub ContextChangedHostType = "github" + ContextChangedHostTypeAdo ContextChangedHostType = "ado" +) + // Type discriminator for UserMessageAttachment. type UserMessageAttachmentType string @@ -2304,6 +2320,18 @@ const ( McpServersLoadedServerStatusNotConfigured McpServersLoadedServerStatus = "not_configured" ) +// New connection status: connected, failed, needs-auth, pending, disabled, or not_configured +type McpServerStatusChangedStatus string + +const ( + McpServerStatusChangedStatusConnected McpServerStatusChangedStatus = "connected" + McpServerStatusChangedStatusFailed McpServerStatusChangedStatus = "failed" + McpServerStatusChangedStatusNeedsAuth McpServerStatusChangedStatus = "needs-auth" + McpServerStatusChangedStatusPending McpServerStatusChangedStatus = "pending" + McpServerStatusChangedStatusDisabled McpServerStatusChangedStatus = "disabled" + McpServerStatusChangedStatusNotConfigured McpServerStatusChangedStatus = "not_configured" +) + // Discovery source type ExtensionsLoadedExtensionSource string diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 0caa777b0..96da352e8 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -302,11 +302,9 @@ interface EventVariant { let generatedEnums = new Map(); function getOrCreateEnum(parentClassName: string, propName: string, values: string[], enumOutput: string[], description?: string, explicitName?: string): string { - const valuesKey = [...values].sort().join("|"); - for (const [, existing] of generatedEnums) { - if ([...existing.values].sort().join("|") === valuesKey) return existing.enumName; - } const enumName = explicitName ?? `${parentClassName}${propName}`; + const existing = generatedEnums.get(enumName); + if (existing) return existing.enumName; generatedEnums.set(enumName, { enumName, values }); const lines: string[] = []; @@ -992,10 +990,10 @@ function emitServerInstanceMethod( const isReq = requiredSet.has(pName); const jsonSchema = pSchema as JSONSchema7; let csType: string; - // If the property has an enum, resolve to the generated enum type + // If the property has an enum, resolve to the generated enum type by title if (jsonSchema.enum && Array.isArray(jsonSchema.enum) && requestClassName) { - const valuesKey = [...jsonSchema.enum].sort().join("|"); - const match = [...generatedEnums.values()].find((e) => [...e.values].sort().join("|") === valuesKey); + const enumTitle = (jsonSchema.title as string) ?? `${requestClassName}${toPascalCase(pName)}`; + const match = generatedEnums.get(enumTitle); csType = match ? (isReq ? match.enumName : `${match.enumName}?`) : schemaTypeToCSharp(jsonSchema, isReq, rpcKnownTypes); } else { csType = schemaTypeToCSharp(jsonSchema, isReq, rpcKnownTypes); diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 6467f22d3..980fb3b8e 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -214,7 +214,7 @@ interface GoEventVariant { interface GoCodegenCtx { structs: string[]; enums: string[]; - enumsByValues: Map; // sorted-values-key → enumName + enumsByName: Map; // enumName → enumName (dedup by type name, not values) generatedNames: Set; } @@ -268,7 +268,8 @@ function findGoDiscriminator( } /** - * Get or create a Go enum type, deduplicating by value set. + * Get or create a Go enum type, deduplicating by type name (not by value set). + * Two enums with the same values but different names are distinct types. */ function getOrCreateGoEnum( enumName: string, @@ -276,8 +277,7 @@ function getOrCreateGoEnum( ctx: GoCodegenCtx, description?: string ): string { - const valuesKey = [...values].sort().join("|"); - const existing = ctx.enumsByValues.get(valuesKey); + const existing = ctx.enumsByName.get(enumName); if (existing) return existing; const lines: string[] = []; @@ -302,7 +302,7 @@ function getOrCreateGoEnum( } lines.push(`)`); - ctx.enumsByValues.set(valuesKey, enumName); + ctx.enumsByName.set(enumName, enumName); ctx.enums.push(lines.join("\n")); return enumName; } @@ -578,7 +578,7 @@ function generateGoSessionEventsCode(schema: JSONSchema7): string { const ctx: GoCodegenCtx = { structs: [], enums: [], - enumsByValues: new Map(), + enumsByName: new Map(), generatedNames: new Set(), };