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 b06b68676..44b30bd9d 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -155,8 +155,8 @@ 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")] @@ -187,8 +187,8 @@ 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")] @@ -203,8 +203,8 @@ 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")] @@ -231,12 +231,48 @@ public class AccountGetQuotaResultQuotaSnapshotsValue public string? 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 Dictionary QuotaSnapshots { get => field ??= []; set; } + public Dictionary QuotaSnapshots { get => field ??= []; set; } +} + +/// RPC data type for DiscoveredMcpServer operations. +public class DiscoveredMcpServer +{ + /// Server name (config key). + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// Server type: local, stdio, http, or sse. + [JsonPropertyName("type")] + public string? Type { get; set; } + + /// Configuration source. + [JsonPropertyName("source")] + public DiscoveredMcpServerSource Source { get; set; } + + /// Whether the server is enabled (not in the disabled list). + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } +} + +/// RPC data type for McpDiscover operations. +public class McpDiscoverResult +{ + /// MCP servers discovered from all sources. + [JsonPropertyName("servers")] + public List Servers { get => field ??= []; set; } +} + +/// RPC data type for McpDiscover operations. +internal class McpDiscoverRequest +{ + /// Working directory used as context for discovery (e.g., plugin resolution). + [JsonPropertyName("workingDirectory")] + public string? WorkingDirectory { get; set; } } /// RPC data type for SessionFsSetProvider operations. @@ -260,7 +296,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. @@ -285,16 +321,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")] @@ -306,7 +342,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")] @@ -317,8 +353,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")] @@ -333,8 +369,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")] @@ -401,8 +437,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")] @@ -421,12 +457,12 @@ internal class SessionModelSwitchToRequest public ModelCapabilitiesOverride? ModelCapabilities { get; set; } } -/// RPC data type for SessionModeGet operations. -public class SessionModeGetResult +/// RPC data type for ModeGet operations. +public class ModeGetResult { - /// The current agent mode. + /// The current agent mode. Valid values: "interactive", "plan", "autopilot". [JsonPropertyName("mode")] - public SessionModeGetResultMode Mode { get; set; } + public SessionMode Mode { get; set; } } /// RPC data type for SessionModeGet operations. @@ -437,28 +473,28 @@ internal class SessionModeGetRequest public string SessionId { get; set; } = string.Empty; } -/// RPC data type for SessionModeSet operations. -public class SessionModeSetResult +/// RPC data type for ModeSet operations. +public class ModeSetResult { - /// The agent mode after switching. + /// The agent mode after switching. Valid values: "interactive", "plan", "autopilot". [JsonPropertyName("mode")] - public SessionModeGetResultMode Mode { get; set; } + public SessionMode 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 to switch to. 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")] @@ -481,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")] @@ -498,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 { } @@ -511,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")] @@ -527,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")] @@ -547,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")] @@ -568,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")] @@ -606,9 +642,9 @@ 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")] @@ -624,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")] @@ -640,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. @@ -659,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")] @@ -674,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")] @@ -696,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 { } @@ -711,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 List Agents { get => field ??= []; set; } + public List Agents { get => field ??= []; set; } } /// RPC data type for SessionAgentReload operations. @@ -757,9 +809,9 @@ 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")] @@ -775,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")] @@ -794,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")] @@ -813,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 { } @@ -828,8 +880,8 @@ 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). [JsonPropertyName("name")] @@ -837,7 +889,7 @@ public class Server /// 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")] @@ -848,13 +900,13 @@ public class Server 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 List Servers { get => field ??= []; set; } + public List Servers { get => field ??= []; set; } } /// RPC data type for SessionMcpList operations. @@ -866,15 +918,15 @@ 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")] @@ -885,15 +937,15 @@ internal class SessionMcpEnableRequest 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")] @@ -904,9 +956,9 @@ internal class SessionMcpDisableRequest 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 { } @@ -939,9 +991,9 @@ 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")] @@ -981,9 +1033,9 @@ public class Extension public double? 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")] @@ -999,15 +1051,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")] @@ -1018,15 +1070,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")] @@ -1037,9 +1089,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 { } @@ -1052,44 +1104,44 @@ 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")] public string SessionId { get; set; } = string.Empty; - /// Gets or sets the requestId value. + /// Request ID of the pending tool call. [JsonPropertyName("requestId")] public string RequestId { get; set; } = string.Empty; - /// Gets or sets the result value. + /// Tool call result (string or expanded result object). [JsonPropertyName("result")] public object? Result { get; set; } - /// Gets or sets the error value. + /// Error message if the tool call failed. [JsonPropertyName("error")] public string? Error { get; set; } } -/// RPC data type for SessionCommandsHandlePendingCommand operations. -public class SessionCommandsHandlePendingCommandResult +/// RPC data type for CommandsHandlePendingCommand operations. +public class CommandsHandlePendingCommandResult { - /// Gets or sets the success value. + /// 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")] @@ -1104,12 +1156,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 UiElicitationAction Action { get; set; } /// The form values submitted by the user (present when action is 'accept'). [JsonPropertyName("content")] @@ -1117,7 +1169,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")] @@ -1132,8 +1184,8 @@ public class SessionUiElicitationRequestRequestedSchema public List? 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")] @@ -1145,31 +1197,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 Dictionary? 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")] @@ -1181,25 +1221,25 @@ 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")] public string SessionId { get; set; } = string.Empty; - /// Gets or sets the requestId value. + /// Request ID of the pending permission request. [JsonPropertyName("requestId")] public string RequestId { get; set; } = string.Empty; @@ -1208,16 +1248,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")] @@ -1236,16 +1276,16 @@ internal class SessionShellExecRequest public double? 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")] @@ -1257,12 +1297,40 @@ internal class SessionShellKillRequest /// Signal to send (default: SIGTERM). [JsonPropertyName("signal")] - public SessionShellKillRequestSignal? Signal { get; set; } + public ShellKillSignal? Signal { get; set; } } -/// RPC data type for SessionHistoryCompact operations. +/// Post-compaction context window usage breakdown. +public class HistoryCompactContextWindow +{ + /// Maximum token count for the model's context window. + [JsonPropertyName("tokenLimit")] + public double TokenLimit { get; set; } + + /// Current total tokens in the context window (system + conversation + tool definitions). + [JsonPropertyName("currentTokens")] + public double CurrentTokens { get; set; } + + /// Current number of messages in the conversation. + [JsonPropertyName("messagesLength")] + public double MessagesLength { get; set; } + + /// Token count from system message(s). + [JsonPropertyName("systemTokens")] + public double? SystemTokens { get; set; } + + /// Token count from non-system messages (user, assistant, tool). + [JsonPropertyName("conversationTokens")] + public double? ConversationTokens { get; set; } + + /// Token count from tool definitions. + [JsonPropertyName("toolDefinitionsTokens")] + public double? ToolDefinitionsTokens { get; set; } +} + +/// RPC data type for HistoryCompact operations. [Experimental(Diagnostics.Experimental)] -public class SessionHistoryCompactResult +public class HistoryCompact { /// Whether compaction completed successfully. [JsonPropertyName("success")] @@ -1275,6 +1343,10 @@ public class SessionHistoryCompactResult /// Number of messages removed during compaction. [JsonPropertyName("messagesRemoved")] public double MessagesRemoved { get; set; } + + /// Post-compaction context window usage breakdown. + [JsonPropertyName("contextWindow")] + public HistoryCompactContextWindow? ContextWindow { get; set; } } /// RPC data type for SessionHistoryCompact operations. @@ -1286,18 +1358,18 @@ 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. [JsonPropertyName("eventsRemoved")] public double 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")] @@ -1308,6 +1380,120 @@ internal class SessionHistoryTruncateRequest public string EventId { get; set; } = string.Empty; } +/// Aggregated code change metrics. +public class UsageMetricsCodeChanges +{ + /// Total lines of code added. + [JsonPropertyName("linesAdded")] + public double LinesAdded { get; set; } + + /// Total lines of code removed. + [JsonPropertyName("linesRemoved")] + public double LinesRemoved { get; set; } + + /// Number of distinct files modified. + [JsonPropertyName("filesModifiedCount")] + public double FilesModifiedCount { get; set; } +} + +/// Request count and cost metrics for this model. +public class UsageMetricsModelMetricRequests +{ + /// Number of API requests made with this model. + [JsonPropertyName("count")] + public double Count { get; set; } + + /// User-initiated premium request cost (with multiplier applied). + [JsonPropertyName("cost")] + public double Cost { get; set; } +} + +/// Token usage metrics for this model. +public class UsageMetricsModelMetricUsage +{ + /// Total input tokens consumed. + [JsonPropertyName("inputTokens")] + public double InputTokens { get; set; } + + /// Total output tokens produced. + [JsonPropertyName("outputTokens")] + public double OutputTokens { get; set; } + + /// Total tokens read from prompt cache. + [JsonPropertyName("cacheReadTokens")] + public double CacheReadTokens { get; set; } + + /// Total tokens written to prompt cache. + [JsonPropertyName("cacheWriteTokens")] + public double CacheWriteTokens { get; set; } + + /// Total output tokens used for reasoning. + [JsonPropertyName("reasoningTokens")] + public double? ReasoningTokens { get; set; } +} + +/// RPC data type for UsageMetricsModelMetric operations. +public class UsageMetricsModelMetric +{ + /// Request count and cost metrics for this model. + [JsonPropertyName("requests")] + public UsageMetricsModelMetricRequests Requests { get => field ??= new(); set; } + + /// Token usage metrics for this model. + [JsonPropertyName("usage")] + public UsageMetricsModelMetricUsage Usage { get => field ??= new(); set; } +} + +/// RPC data type for UsageMetrics operations. +[Experimental(Diagnostics.Experimental)] +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. + [JsonPropertyName("totalUserRequests")] + public double TotalUserRequests { get; set; } + + /// Total time spent in model API calls (milliseconds). + [JsonPropertyName("totalApiDurationMs")] + public double TotalApiDurationMs { get; set; } + + /// Session start timestamp (epoch milliseconds). + [JsonPropertyName("sessionStartTime")] + public double SessionStartTime { get; set; } + + /// Aggregated code change metrics. + [JsonPropertyName("codeChanges")] + public UsageMetricsCodeChanges CodeChanges { get => field ??= new(); set; } + + /// Per-model token and request metrics, keyed by model identifier. + [JsonPropertyName("modelMetrics")] + public Dictionary ModelMetrics { get => field ??= []; set; } + + /// Currently active model identifier. + [JsonPropertyName("currentModel")] + public string? CurrentModel { get; set; } + + /// Input tokens from the most recent main-agent API call. + [JsonPropertyName("lastCallInputTokens")] + public double LastCallInputTokens { get; set; } + + /// Output tokens from the most recent main-agent API call. + [JsonPropertyName("lastCallOutputTokens")] + public double LastCallOutputTokens { get; set; } +} + +/// RPC data type for SessionUsageGetMetrics operations. +[Experimental(Diagnostics.Experimental)] +internal class SessionUsageGetMetricsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + /// RPC data type for SessionFsReadFile operations. public class SessionFsReadFileResult { @@ -1317,7 +1503,7 @@ public class SessionFsReadFileResult } /// RPC data type for SessionFsReadFile operations. -public class SessionFsReadFileParams +public class SessionFsReadFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1329,7 +1515,7 @@ public class SessionFsReadFileParams } /// RPC data type for SessionFsWriteFile operations. -public class SessionFsWriteFileParams +public class SessionFsWriteFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1349,7 +1535,7 @@ public class SessionFsWriteFileParams } /// RPC data type for SessionFsAppendFile operations. -public class SessionFsAppendFileParams +public class SessionFsAppendFileRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1377,7 +1563,7 @@ public class SessionFsExistsResult } /// RPC data type for SessionFsExists operations. -public class SessionFsExistsParams +public class SessionFsExistsRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1413,7 +1599,7 @@ public class SessionFsStatResult } /// RPC data type for SessionFsStat operations. -public class SessionFsStatParams +public class SessionFsStatRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1425,7 +1611,7 @@ public class SessionFsStatParams } /// RPC data type for SessionFsMkdir operations. -public class SessionFsMkdirParams +public class SessionFsMkdirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1453,7 +1639,7 @@ public class SessionFsReaddirResult } /// RPC data type for SessionFsReaddir operations. -public class SessionFsReaddirParams +public class SessionFsReaddirRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1464,8 +1650,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")] @@ -1473,7 +1659,7 @@ public class Entry /// Entry type. [JsonPropertyName("type")] - public EntryType Type { get; set; } + public SessionFsReaddirWithTypesEntryType Type { get; set; } } /// RPC data type for SessionFsReaddirWithTypes operations. @@ -1481,11 +1667,11 @@ public class SessionFsReaddirWithTypesResult { /// Directory entries with type information. [JsonPropertyName("entries")] - public List Entries { get => field ??= []; set; } + public List Entries { get => field ??= []; set; } } /// RPC data type for SessionFsReaddirWithTypes operations. -public class SessionFsReaddirWithTypesParams +public class SessionFsReaddirWithTypesRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1497,7 +1683,7 @@ public class SessionFsReaddirWithTypesParams } /// RPC data type for SessionFsRm operations. -public class SessionFsRmParams +public class SessionFsRmRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1517,7 +1703,7 @@ public class SessionFsRmParams } /// RPC data type for SessionFsRename operations. -public class SessionFsRenameParams +public class SessionFsRenameRequest { /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1532,9 +1718,28 @@ public class SessionFsRenameParams public string Dest { get; set; } = string.Empty; } +/// Configuration source. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum DiscoveredMcpServerSource +{ + /// The user variant. + [JsonStringEnumMemberName("user")] + User, + /// The workspace variant. + [JsonStringEnumMemberName("workspace")] + Workspace, + /// The plugin variant. + [JsonStringEnumMemberName("plugin")] + Plugin, + /// The builtin variant. + [JsonStringEnumMemberName("builtin")] + Builtin, +} + + /// Path conventions used by this filesystem. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionFsSetProviderRequestConventions +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionFsSetProviderConventions { /// The windows variant. [JsonStringEnumMemberName("windows")] @@ -1546,8 +1751,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")] @@ -1561,9 +1766,9 @@ public enum SessionLogRequestLevel } -/// The current agent mode. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionModeGetResultMode +/// The current agent mode. Valid values: "interactive", "plan", "autopilot". +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionMode { /// The interactive variant. [JsonStringEnumMemberName("interactive")] @@ -1578,8 +1783,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")] @@ -1635,8 +1840,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 UiElicitationAction { /// The accept variant. [JsonStringEnumMemberName("accept")] @@ -1651,8 +1856,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")] @@ -1667,8 +1872,8 @@ public enum SessionShellKillRequestSignal /// Entry type. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum EntryType +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum SessionFsReaddirWithTypesEntryType { /// The file variant. [JsonStringEnumMemberName("file")] @@ -1732,9 +1937,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); } } @@ -1749,10 +1954,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); } } @@ -1767,9 +1972,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); } } @@ -1782,6 +1987,13 @@ internal ServerMcpApi(JsonRpc rpc) { _rpc = rpc; } + + /// Calls "mcp.discover". + public async Task DiscoverAsync(string? workingDirectory = null, CancellationToken cancellationToken = default) + { + var request = new McpDiscoverRequest { WorkingDirectory = workingDirectory }; + return await CopilotClient.InvokeRpcAsync(_rpc, "mcp.discover", [request], cancellationToken); + } } /// Provides server-scoped SessionFs APIs. @@ -1795,7 +2007,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); @@ -1847,6 +2059,7 @@ internal SessionRpc(JsonRpc rpc, string sessionId) Permissions = new PermissionsApi(rpc, sessionId); Shell = new ShellApi(rpc, sessionId); History = new HistoryApi(rpc, sessionId); + Usage = new UsageApi(rpc, sessionId); } /// Model APIs. @@ -1897,11 +2110,14 @@ internal SessionRpc(JsonRpc rpc, string sessionId) /// History APIs. public HistoryApi History { get; } + /// Usage APIs. + 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); } } @@ -1918,17 +2134,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); } } @@ -1945,17 +2161,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); } } @@ -1972,24 +2188,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); } } @@ -2006,24 +2222,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); } } @@ -2041,10 +2257,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); } } @@ -2062,38 +2278,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); } } @@ -2111,31 +2327,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); } } @@ -2153,31 +2369,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); } } @@ -2195,10 +2411,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); } } @@ -2216,31 +2432,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); } } @@ -2257,10 +2473,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); } } @@ -2277,10 +2493,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); } } @@ -2297,17 +2513,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); } } @@ -2324,10 +2540,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); } } @@ -2344,17 +2560,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, double? 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); } } @@ -2372,17 +2588,38 @@ 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 HistoryTruncateRequest { SessionId = _sessionId, EventId = eventId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.truncate", [request], cancellationToken); + } +} + +/// Provides session-scoped Usage APIs. +[Experimental(Diagnostics.Experimental)] +public class UsageApi +{ + private readonly JsonRpc _rpc; + private readonly string _sessionId; + + internal UsageApi(JsonRpc rpc, string sessionId) + { + _rpc = rpc; + _sessionId = sessionId; + } + + /// Calls "session.usage.getMetrics". + public async Task GetMetricsAsync(CancellationToken cancellationToken = default) { - var request = new SessionHistoryTruncateRequest { SessionId = _sessionId, EventId = eventId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "session.history.truncate", [request], cancellationToken); + var request = new SessionUsageGetMetricsRequest { SessionId = _sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "session.usage.getMetrics", [request], cancellationToken); } } @@ -2390,25 +2627,25 @@ public async Task TruncateAsync(string eventId, Ca 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. @@ -2428,7 +2665,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}"); @@ -2438,7 +2675,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}"); @@ -2448,7 +2685,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}"); @@ -2458,7 +2695,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}"); @@ -2468,7 +2705,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}"); @@ -2478,7 +2715,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}"); @@ -2488,7 +2725,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}"); @@ -2498,7 +2735,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}"); @@ -2508,7 +2745,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}"); @@ -2518,7 +2755,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}"); @@ -2535,11 +2772,50 @@ 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)] @@ -1156,7 +1156,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)] @@ -1300,7 +1300,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. @@ -1312,7 +1312,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. @@ -1324,12 +1324,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)] @@ -1405,7 +1405,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)] @@ -1426,7 +1426,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")] @@ -1478,7 +1478,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)] @@ -1606,7 +1606,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)] @@ -1658,7 +1658,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)] @@ -1668,7 +1668,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)] @@ -1748,7 +1748,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)] @@ -1843,6 +1843,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")] @@ -1891,7 +1896,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)] @@ -2009,12 +2014,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)] @@ -2220,7 +2225,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. @@ -2232,7 +2237,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)] @@ -2242,7 +2247,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. @@ -2254,7 +2259,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. @@ -2283,7 +2288,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. @@ -2355,12 +2360,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)] @@ -2378,7 +2383,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)] @@ -2428,7 +2433,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. @@ -2527,7 +2532,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. @@ -2536,7 +2541,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. @@ -2609,7 +2614,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 . @@ -2617,7 +2622,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")] @@ -2633,7 +2638,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 . @@ -2645,7 +2650,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 . @@ -2653,12 +2658,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")] @@ -2677,7 +2682,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)] @@ -2696,8 +2701,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")] @@ -2716,7 +2721,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)] @@ -2735,8 +2740,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")] @@ -2753,8 +2758,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")] @@ -2770,8 +2775,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")] @@ -2787,8 +2792,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")] @@ -2800,8 +2805,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] @@ -2818,12 +2823,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] @@ -2839,8 +2844,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")] @@ -2852,8 +2857,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")] @@ -2865,21 +2870,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] @@ -2899,12 +2904,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] @@ -2920,7 +2925,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")] @@ -2932,8 +2937,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] @@ -2958,12 +2963,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")] @@ -2972,8 +2977,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")] @@ -2991,7 +2996,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)] @@ -3010,8 +3015,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")] @@ -3031,12 +3036,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")] @@ -3044,8 +3049,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] @@ -3057,8 +3062,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] @@ -3080,8 +3085,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] @@ -3097,8 +3102,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] @@ -3114,8 +3119,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")] @@ -3134,12 +3139,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] @@ -3148,7 +3153,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")] @@ -3180,8 +3185,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] @@ -3197,13 +3202,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")] @@ -3212,8 +3217,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")] @@ -3227,12 +3232,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")] @@ -3245,8 +3250,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")] @@ -3259,8 +3264,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)] @@ -3273,8 +3278,8 @@ public partial class SystemMessageDataMetadata public Dictionary? Variables { get; set; } } -/// The agent_completed variant of . -public partial class SystemNotificationDataKindAgentCompleted : SystemNotificationDataKind +/// The agent_completed variant of . +public partial class SystemNotificationAgentCompleted : SystemNotification { /// [JsonIgnore] @@ -3290,7 +3295,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)] @@ -3303,8 +3308,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] @@ -3324,8 +3329,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] @@ -3346,8 +3351,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] @@ -3368,11 +3373,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")] @@ -3380,8 +3385,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")] @@ -3392,8 +3397,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")] @@ -3423,7 +3428,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")] @@ -3431,7 +3436,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")] @@ -3557,7 +3562,7 @@ public partial class PermissionRequestUrl : PermissionRequest public required string Url { get; set; } } -/// Memory storage permission request. +/// Memory operation permission request. /// The memory variant of . public partial class PermissionRequestMemory : PermissionRequest { @@ -3570,17 +3575,34 @@ public partial class PermissionRequestMemory : PermissionRequest [JsonPropertyName("toolCallId")] public string? ToolCallId { get; set; } - /// Topic or subject of the memory being stored. + /// Whether this is a store or vote memory operation. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("action")] + public PermissionRequestMemoryAction? Action { get; set; } + + /// Topic or subject of the memory (store only). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("subject")] - public required string Subject { get; set; } + public string? Subject { get; set; } - /// The fact or convention being stored. + /// The fact being stored or voted on. [JsonPropertyName("fact")] public required string Fact { get; set; } - /// Source references for the stored fact. + /// Source references for the stored fact (store only). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("citations")] - public required string Citations { get; set; } + public string? Citations { get; set; } + + /// Vote direction (vote only). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("direction")] + public PermissionRequestMemoryDirection? Direction { get; set; } + + /// Reason for the vote (vote only). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("reason")] + public string? Reason { get; set; } } /// Custom tool invocation permission request. @@ -3660,17 +3682,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")] @@ -3687,8 +3709,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")] @@ -3700,8 +3722,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")] @@ -3714,8 +3736,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)] @@ -3723,8 +3745,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")] @@ -3752,8 +3774,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")] @@ -3789,8 +3811,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")] @@ -3798,7 +3820,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)] @@ -3811,8 +3833,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")] @@ -3824,16 +3846,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")] @@ -3844,8 +3866,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")] @@ -3859,8 +3881,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")] @@ -3871,8 +3893,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")] @@ -3883,8 +3905,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")] @@ -3895,8 +3917,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")] @@ -3910,8 +3932,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")] @@ -3928,8 +3950,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")] @@ -3940,8 +3962,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")] @@ -3952,8 +3974,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")] @@ -3964,8 +3986,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")] @@ -3975,9 +3997,33 @@ public enum SystemNotificationDataKindAgentCompletedStatus Failed, } +/// Whether this is a store or vote memory operation. +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum PermissionRequestMemoryAction +{ + /// The store variant. + [JsonStringEnumMemberName("store")] + Store, + /// The vote variant. + [JsonStringEnumMemberName("vote")] + Vote, +} + +/// Vote direction (vote only). +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum PermissionRequestMemoryDirection +{ + /// The upvote variant. + [JsonStringEnumMemberName("upvote")] + Upvote, + /// The downvote variant. + [JsonStringEnumMemberName("downvote")] + Downvote, +} + /// The outcome of the permission request. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum PermissionCompletedDataResultKind +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum PermissionCompletedKind { /// The approved variant. [JsonStringEnumMemberName("approved")] @@ -4000,8 +4046,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")] @@ -4012,8 +4058,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")] @@ -4027,8 +4073,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")] @@ -4051,8 +4097,8 @@ public enum SessionMcpServersLoadedDataServersItemStatus } /// Discovery source. -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SessionExtensionsLoadedDataExtensionsItemSource +[JsonConverter(typeof(JsonStringEnumConverter))] +public enum ExtensionsLoadedExtensionSource { /// The project variant. [JsonStringEnumMemberName("project")] @@ -4063,8 +4109,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")] @@ -4090,10 +4136,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))] @@ -4104,50 +4150,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))] @@ -4155,12 +4206,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))] @@ -4168,23 +4220,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))] @@ -4193,7 +4241,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))] @@ -4204,18 +4251,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))] @@ -4231,8 +4274,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))] @@ -4244,27 +4290,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))] @@ -4277,17 +4323,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 4e5142cb8..292a345b3 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -733,7 +733,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 @@ -744,9 +744,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) @@ -777,7 +777,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, @@ -790,7 +790,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 @@ -800,7 +800,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)) { @@ -818,7 +818,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 @@ -828,7 +828,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)) { @@ -853,14 +853,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)) { @@ -1141,12 +1141,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); } @@ -1225,7 +1225,7 @@ internal record SendMessageRequest { public string SessionId { get; init; } = string.Empty; public string Prompt { get; init; } = string.Empty; - public List? Attachments { get; init; } + public List? Attachments { get; init; } public string? Mode { get; init; } public string? Traceparent { get; init; } public string? Tracestate { get; init; } @@ -1267,7 +1267,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 2f81f3b4c..bb5e09cd8 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; } } /// @@ -640,7 +640,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). @@ -739,7 +739,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; } @@ -2032,7 +2032,7 @@ protected MessageOptions(MessageOptions? other) /// /// File or data attachments to include with the message. /// - public List? Attachments { get; set; } + public List? Attachments { get; set; } /// /// Interaction mode for the message (e.g., "plan", "edit"). /// diff --git a/dotnet/test/CloneTests.cs b/dotnet/test/CloneTests.cs index a0051ffbc..1ef4f8110 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 e3048e4c9..10876b175 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..312f8b632 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.Mode); // 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.Mode); // Verify mode persisted var afterPlan = await session.Rpc.Mode.GetAsync(); - Assert.Equal(SessionModeGetResultMode.Plan, afterPlan.Mode); + Assert.Equal(SessionMode.Plan, afterPlan.Mode); // 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.Mode); } [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 9bd03f186..26106e2da 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 f8d29cc98..bcf5ea189 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 0599e7fcc..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 @@ -1993,12 +1997,18 @@ type PermissionRequestedDataPermissionRequest struct { ReadOnly *bool `json:"readOnly,omitempty"` // URL to be fetched URL *string `json:"url,omitempty"` - // Topic or subject of the memory being stored + // Whether this is a store or vote memory operation + Action *PermissionRequestMemoryAction `json:"action,omitempty"` + // Topic or subject of the memory (store only) Subject *string `json:"subject,omitempty"` - // The fact or convention being stored + // The fact being stored or voted on Fact *string `json:"fact,omitempty"` - // Source references for the stored fact + // Source references for the stored fact (store only) Citations *string `json:"citations,omitempty"` + // Vote direction (vote only) + Direction *PermissionRequestMemoryDirection `json:"direction,omitempty"` + // Reason for the vote (vote only) + Reason *string `json:"reason,omitempty"` // Description of what the custom tool does ToolDescription *string `json:"toolDescription,omitempty"` // Arguments of the tool call being gated @@ -2008,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 @@ -2024,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 @@ -2057,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 @@ -2076,249 +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 PermissionRequestMemoryAction string + +const ( + PermissionRequestMemoryActionStore PermissionRequestMemoryAction = "store" + PermissionRequestMemoryActionVote PermissionRequestMemoryAction = "vote" +) + +// Vote direction (vote only) +type PermissionRequestMemoryDirection string + +const ( + 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..5788d52c6 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,16 +218,16 @@ func TestSessionRpc(t *testing.T) { if err != nil { t.Fatalf("Failed to get mode: %v", err) } - if initial.Mode != rpc.ModeInteractive { + if initial.Mode != rpc.SessionModeInteractive { t.Errorf("Expected initial mode 'interactive', got %q", initial.Mode) } // 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 { + if planResult.Mode != rpc.SessionModePlan { t.Errorf("Expected mode 'plan', got %q", planResult.Mode) } @@ -236,16 +236,16 @@ func TestSessionRpc(t *testing.T) { if err != nil { t.Fatalf("Failed to get mode after plan: %v", err) } - if afterPlan.Mode != rpc.ModePlan { + if afterPlan.Mode != rpc.SessionModePlan { t.Errorf("Expected mode 'plan' after set, got %q", afterPlan.Mode) } // 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 { + if interactiveResult.Mode != rpc.SessionModeInteractive { t.Errorf("Expected mode 'interactive', got %q", interactiveResult.Mode) } }) @@ -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 6782f499d..7a0e4fc66 100644 --- a/go/rpc/generated_rpc.go +++ b/go/rpc/generated_rpc.go @@ -20,44 +20,39 @@ type PingResult struct { Timestamp float64 `json:"timestamp"` } -type PingParams struct { +type PingRequest struct { // Optional message to echo back Message *string `json:"message,omitempty"` } -type ModelsListResult struct { +type ModelList struct { // List of available models with full metadata Models []Model `json:"models"` } type Model struct { - // Billing information - Billing *Billing `json:"billing,omitempty"` - // Model capabilities and limits + 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"` // Model identifier (e.g., "claude-sonnet-4.5") 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"` } // Billing information -type Billing struct { +type ModelBilling struct { // Billing cost multiplier relative to the base rate 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"` } @@ -68,9 +63,8 @@ type ModelCapabilitiesLimits struct { // Maximum number of output/completion tokens MaxOutputTokens *float64 `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 *float64 `json:"max_prompt_tokens,omitempty"` + Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"` } // Vision-specific limits @@ -92,14 +86,14 @@ type ModelCapabilitiesSupports struct { } // Policy state (if applicable) -type Policy struct { +type ModelPolicy struct { // Current policy state for this model State string `json:"state"` // Usage terms or conditions for this model Terms string `json:"terms"` } -type ToolsListResult struct { +type ToolList struct { // List of available built-in tools with metadata Tools []Tool `json:"tools"` } @@ -118,18 +112,18 @@ type Tool struct { 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"` } -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 { +type AccountQuotaSnapshot struct { // Number of requests included in the entitlement EntitlementRequests float64 `json:"entitlementRequests"` // Number of overage requests made this period @@ -144,92 +138,109 @@ type QuotaSnapshot struct { UsedRequests float64 `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 *float64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,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"` } // 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 *float64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,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"` } // 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 *float64 `json:"timeout,omitempty"` // Tools to include. Defaults to all tools if not specified. Tools []string `json:"tools,omitempty"` - Type *ServerType `json:"type,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"` } +type MCPDiscoverResult struct { + // MCP servers discovered from all sources + Servers []DiscoveredMCPServer `json:"servers"` +} + +type DiscoveredMCPServer struct { + // Whether the server is enabled (not in the disabled list) + Enabled bool `json:"enabled"` + // Server name (config key) + Name string `json:"name"` + Source DiscoveredMCPServerSource `json:"source"` + // Server type: local, stdio, http, or sse + Type *string `json:"type,omitempty"` +} + +type MCPDiscoverRequest struct { + // Working directory used as context for discovery (e.g., plugin resolution) + WorkingDirectory *string `json:"workingDirectory,omitempty"` +} + type SessionFSSetProviderResult struct { // Whether the provider was set successfully 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"` // Path within each session's SessionFs where the runtime stores files for that session @@ -242,8 +253,8 @@ type SessionsForkResult struct { 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"` // Optional event ID boundary. When provided, the fork includes only events before this ID @@ -251,18 +262,17 @@ type SessionsForkParams struct { ToEventID *string `json:"toEventId,omitempty"` } -type SessionModelGetCurrentResult struct { +type ModelCurrent struct { // Currently active model identifier ModelID *string `json:"modelId,omitempty"` } -type SessionModelSwitchToResult struct { +type ModelSwitchToResult struct { // Currently active model identifier after the switch ModelID *string `json:"modelId,omitempty"` } -type SessionModelSwitchToParams struct { - // Override individual model capabilities resolved by the runtime +type ModelSwitchToRequest struct { ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"` // Model identifier to switch to ModelID string `json:"modelId"` @@ -272,9 +282,7 @@ type SessionModelSwitchToParams struct { // 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"` } @@ -302,22 +310,19 @@ type ModelCapabilitiesOverrideSupports struct { Vision *bool `json:"vision,omitempty"` } -type SessionModeGetResult struct { - // The current agent mode. - Mode Mode `json:"mode"` +type ModeGetResult struct { + Mode SessionMode `json:"mode"` } -type SessionModeSetResult struct { - // The agent mode after switching. - Mode Mode `json:"mode"` +type ModeSetResult struct { + Mode SessionMode `json:"mode"` } -type SessionModeSetParams struct { - // The mode to switch to. Valid values: "interactive", "plan", "autopilot". - Mode Mode `json:"mode"` +type ModeSetRequest struct { + Mode SessionMode `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"` // Whether the plan file exists in the workspace @@ -326,61 +331,61 @@ type SessionPlanReadResult struct { 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"` } -type SessionPlanDeleteResult struct { +type PlanDelete struct { } -type SessionWorkspaceListFilesResult struct { +type WorkspaceFiles struct { // Relative file paths in the workspace files directory Files []string `json:"files"` } -type SessionWorkspaceReadFileResult struct { +type WorkspaceReadFileResult struct { // File content as a UTF-8 string Content string `json:"content"` } -type SessionWorkspaceReadFileParams struct { +type WorkspaceReadFileRequest struct { // Relative path within the workspace files directory 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"` // Relative path within the workspace files directory 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"` } -// 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"` } -// 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"` // Human-readable display name @@ -389,13 +394,13 @@ type SessionAgentListResultAgent struct { 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"` // Human-readable display name @@ -404,14 +409,13 @@ type SessionAgentGetCurrentResultAgent struct { 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"` // Human-readable display name @@ -420,23 +424,23 @@ type SessionAgentSelectResultAgent struct { 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"` } -// 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"` // Human-readable display name @@ -445,8 +449,8 @@ type SessionAgentReloadResultAgent struct { 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"` } @@ -466,72 +470,71 @@ type Skill struct { 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"` } -// 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"` } -// 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"` // 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"` + Source *string `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"` } -type SessionMCPDisableResult struct { +type MCPDisableResult struct { } -type SessionMCPDisableParams struct { +type MCPDisableRequest struct { // Name of the MCP server to disable 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 []Plugin `json:"plugins"` + Plugins []PluginElement `json:"plugins"` } -type Plugin struct { +type PluginElement struct { // Whether the plugin is currently enabled Enabled bool `json:"enabled"` // Marketplace the plugin came from @@ -542,8 +545,8 @@ type Plugin struct { 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"` } @@ -554,187 +557,199 @@ type Extension struct { // Extension name (directory 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 Source `json:"source"` - // Current status: running, disabled, failed, or starting + 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"` } -// 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"` } -// 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"` } -type SessionToolsHandlePendingToolCallParams struct { - Error *string `json:"error,omitempty"` - RequestID string `json:"requestId"` - Result *ResultUnion `json:"result"` +type ToolsHandlePendingToolCallRequest struct { + // Error message if the tool call failed + Error *string `json:"error,omitempty"` + // Request ID of the pending tool call + RequestID string `json:"requestId"` + Result *ToolsHandlePendingToolCall `json:"result"` } -type ResultResult struct { - Error *string `json:"error,omitempty"` - ResultType *string `json:"resultType,omitempty"` - TextResultForLlm string `json:"textResultForLlm"` - ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` +type ToolCallResult struct { + // Error message if the tool call failed + Error *string `json:"error,omitempty"` + // Type of the tool result + ResultType *string `json:"resultType,omitempty"` + // Text result to send back to the LLM + TextResultForLlm string `json:"textResultForLlm"` + // Telemetry data from tool execution + ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"` } -type SessionCommandsHandlePendingCommandResult struct { +type CommandsHandlePendingCommandResult struct { + // Whether the command was handled successfully Success bool `json:"success"` } -type SessionCommandsHandlePendingCommandParams struct { +type CommandsHandlePendingCommandRequest struct { // Error message if the command handler failed Error *string `json:"error,omitempty"` // Request ID from the command invocation event RequestID string `json:"requestId"` } -type SessionUIElicitationResult struct { - // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - Action Action `json:"action"` +// The elicitation response (accept with form values, decline, or cancel) +type UIElicitationResponse struct { + Action UIElicitationAction `json:"action"` // The form values submitted by the user (present when action is 'accept') - Content map[string]*Content `json:"content,omitempty"` + Content map[string]*UIElicitationContent `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"` // 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 UIElicitationSchemaProperty struct { + Default *UIElicitationContent `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 Items struct { - Enum []string `json:"enum,omitempty"` - Type *ItemsType `json:"type,omitempty"` - AnyOf []AnyOf `json:"anyOf,omitempty"` +type ElicitationArrayFieldItems struct { + Enum []string `json:"enum,omitempty"` + Type *ItemsType `json:"type,omitempty"` + AnyOf []ElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"` } -type AnyOf struct { +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"` } -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"` + RequestID string `json:"requestId"` + Result UIElicitationResponse `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"` -} - -type SessionPermissionsHandlePendingPermissionRequestResult struct { +type PermissionRequestResult struct { // Whether the permission request was handled successfully Success bool `json:"success"` } -type SessionPermissionsHandlePendingPermissionRequestParams struct { - RequestID string `json:"requestId"` - Result SessionPermissionsHandlePendingPermissionRequestParamsResult `json:"result"` -} - -type SessionPermissionsHandlePendingPermissionRequestParamsResult struct { - Kind Kind `json:"kind"` - Rules []any `json:"rules,omitempty"` - Feedback *string `json:"feedback,omitempty"` - Message *string `json:"message,omitempty"` - Path *string `json:"path,omitempty"` - Interrupt *bool `json:"interrupt,omitempty"` +type PermissionDecisionRequest struct { + // Request ID of the pending permission request + RequestID string `json:"requestId"` + Result PermissionDecision `json:"result"` +} + +type PermissionDecision struct { + // The permission request was approved + // + // Denied because approval rules explicitly blocked it + // + // Denied because no approval rule matched and user confirmation was unavailable + // + // Denied by the user during an interactive prompt + // + // Denied by the organization's content exclusion policy + // + // Denied by a permission request hook registered by an extension or plugin + Kind Kind `json:"kind"` + // Rules that denied the request + Rules []any `json:"rules,omitempty"` + // Optional feedback from the user explaining the denial + 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"` + // File path that triggered the exclusion + Path *string `json:"path,omitempty"` + // Whether to interrupt the current agent turn + Interrupt *bool `json:"interrupt,omitempty"` } -type SessionLogResult struct { +type LogResult struct { // The unique identifier of the emitted session event 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"` // Optional URL the user can open in their browser for more details URL *string `json:"url,omitempty"` } -type SessionShellExecResult struct { +type ShellExecResult struct { // Unique identifier for tracking streamed output ProcessID string `json:"processId"` } -type SessionShellExecParams struct { +type ShellExecRequest struct { // Shell command to execute Command string `json:"command"` // Working directory (defaults to session working directory) @@ -743,20 +758,20 @@ type SessionShellExecParams struct { Timeout *float64 `json:"timeout,omitempty"` } -type SessionShellKillResult struct { +type ShellKillResult struct { // Whether the signal was sent successfully 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 { +// 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"` // Whether compaction completed successfully @@ -765,31 +780,106 @@ type SessionHistoryCompactResult struct { TokensRemoved float64 `json:"tokensRemoved"` } -// Experimental: SessionHistoryTruncateResult is part of an experimental API and may change or be removed. -type SessionHistoryTruncateResult struct { +// Post-compaction context window usage breakdown +type HistoryCompactContextWindow struct { + // Token count from non-system messages (user, assistant, tool) + ConversationTokens *float64 `json:"conversationTokens,omitempty"` + // Current total tokens in the context window (system + conversation + tool definitions) + CurrentTokens float64 `json:"currentTokens"` + // Current number of messages in the conversation + MessagesLength float64 `json:"messagesLength"` + // Token count from system message(s) + SystemTokens *float64 `json:"systemTokens,omitempty"` + // Maximum token count for the model's context window + TokenLimit float64 `json:"tokenLimit"` + // Token count from tool definitions + ToolDefinitionsTokens *float64 `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 float64 `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"` } +// 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"` + // Input tokens from the most recent main-agent API call + LastCallInputTokens int64 `json:"lastCallInputTokens"` + // Output tokens from the most recent main-agent API call + LastCallOutputTokens int64 `json:"lastCallOutputTokens"` + // Per-model token and request metrics, keyed by model identifier + ModelMetrics map[string]UsageMetricsModelMetric `json:"modelMetrics"` + // Session start timestamp (epoch milliseconds) + SessionStartTime int64 `json:"sessionStartTime"` + // Total time spent in model API calls (milliseconds) + TotalAPIDurationMS float64 `json:"totalApiDurationMs"` + // Total user-initiated premium request cost across all models (may be fractional due to + // multipliers) + TotalPremiumRequestCost float64 `json:"totalPremiumRequestCost"` + // Raw count of user-initiated API requests + TotalUserRequests int64 `json:"totalUserRequests"` +} + +// Aggregated code change metrics +type UsageMetricsCodeChanges struct { + // Number of distinct files modified + FilesModifiedCount int64 `json:"filesModifiedCount"` + // Total lines of code added + LinesAdded int64 `json:"linesAdded"` + // Total lines of code removed + LinesRemoved int64 `json:"linesRemoved"` +} + +type UsageMetricsModelMetric struct { + Requests UsageMetricsModelMetricRequests `json:"requests"` + 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"` + // Number of API requests made with this model + Count int64 `json:"count"` +} + +// Token usage metrics for this model +type UsageMetricsModelMetricUsage struct { + // Total tokens read from prompt cache + CacheReadTokens int64 `json:"cacheReadTokens"` + // Total tokens written to prompt cache + CacheWriteTokens int64 `json:"cacheWriteTokens"` + // Total input tokens consumed + InputTokens int64 `json:"inputTokens"` + // Total output tokens produced + 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"` } -type SessionFSReadFileParams struct { +type SessionFSReadFileRequest struct { // Path using SessionFs conventions Path string `json:"path"` // Target session identifier SessionID string `json:"sessionId"` } -type SessionFSWriteFileParams struct { +type SessionFSWriteFileRequest struct { // Content to write Content string `json:"content"` // Optional POSIX-style mode for newly created files @@ -800,7 +890,7 @@ type SessionFSWriteFileParams struct { SessionID string `json:"sessionId"` } -type SessionFSAppendFileParams struct { +type SessionFSAppendFileRequest struct { // Content to append Content string `json:"content"` // Optional POSIX-style mode for newly created files @@ -816,7 +906,7 @@ type SessionFSExistsResult struct { Exists bool `json:"exists"` } -type SessionFSExistsParams struct { +type SessionFSExistsRequest struct { // Path using SessionFs conventions Path string `json:"path"` // Target session identifier @@ -836,14 +926,14 @@ type SessionFSStatResult struct { Size float64 `json:"size"` } -type SessionFSStatParams struct { +type SessionFSStatRequest struct { // Path using SessionFs conventions Path string `json:"path"` // Target session identifier SessionID string `json:"sessionId"` } -type SessionFSMkdirParams struct { +type SessionFSMkdirRequest struct { // Optional POSIX-style mode for newly created directories Mode *float64 `json:"mode,omitempty"` // Path using SessionFs conventions @@ -859,7 +949,7 @@ type SessionFSReaddirResult struct { Entries []string `json:"entries"` } -type SessionFSReaddirParams struct { +type SessionFSReaddirRequest struct { // Path using SessionFs conventions Path string `json:"path"` // Target session identifier @@ -868,24 +958,23 @@ type SessionFSReaddirParams struct { 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"` // Target session identifier SessionID string `json:"sessionId"` } -type SessionFSRmParams struct { +type SessionFSRmRequest struct { // Ignore errors if the path does not exist Force *bool `json:"force,omitempty"` // Path using SessionFs conventions @@ -896,7 +985,7 @@ type SessionFSRmParams struct { SessionID string `json:"sessionId"` } -type SessionFSRenameParams struct { +type SessionFSRenameRequest struct { // Destination path using SessionFs conventions Dest string `json:"dest"` // Target session identifier @@ -905,62 +994,68 @@ type SessionFSRenameParams struct { 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" + MCPConfigTypeHTTP MCPConfigType = "http" + MCPConfigTypeLocal MCPConfigType = "local" + MCPConfigTypeSse MCPConfigType = "sse" + MCPConfigTypeStdio MCPConfigType = "stdio" +) + +// Configuration source +type DiscoveredMCPServerSource string + +const ( + DiscoveredMCPServerSourceBuiltin DiscoveredMCPServerSource = "builtin" + DiscoveredMCPServerSourceUser DiscoveredMCPServerSource = "user" + DiscoveredMCPServerSourcePlugin DiscoveredMCPServerSource = "plugin" + DiscoveredMCPServerSourceWorkspace DiscoveredMCPServerSource = "workspace" ) // 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 current 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 Source string +type ExtensionSource string const ( - SourceProject Source = "project" - SourceUser Source = "user" + ExtensionSourceUser ExtensionSource = "user" + ExtensionSourceProject ExtensionSource = "project" ) // Current status: running, disabled, failed, or starting @@ -974,21 +1069,21 @@ const ( ) // The user's response: accept (submitted), decline (rejected), or cancel (dismissed) -type Action string +type UIElicitationAction string const ( - ActionAccept Action = "accept" - ActionCancel Action = "cancel" - ActionDecline Action = "decline" + UIElicitationActionAccept UIElicitationAction = "accept" + UIElicitationActionCancel UIElicitationAction = "cancel" + UIElicitationActionDecline UIElicitationAction = "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 @@ -997,14 +1092,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 @@ -1026,42 +1121,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 } -type ResultUnion struct { - ResultResult *ResultResult - String *string +// Tool call result (string or expanded result object) +type ToolsHandlePendingToolCall struct { + String *string + ToolCallResult *ToolCallResult } -type Content struct { +type UIElicitationContent struct { Bool *bool Double *float64 String *string @@ -1074,12 +1170,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 } @@ -1088,12 +1184,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 } @@ -1102,12 +1198,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 } @@ -1116,9 +1212,21 @@ func (a *ServerAccountApi) GetQuota(ctx context.Context) (*AccountGetQuotaResult type ServerMcpApi serverApi +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 + } + var result MCPDiscoverResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + 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 @@ -1133,7 +1241,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 @@ -1157,7 +1265,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 @@ -1188,20 +1296,20 @@ type sessionApi struct { 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 @@ -1216,7 +1324,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 } @@ -1225,20 +1333,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) (*ModeGetResult, 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 ModeGetResult 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) (*ModeSetResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["mode"] = params.Mode @@ -1247,7 +1355,7 @@ func (a *ModeApi) Set(ctx context.Context, params *SessionModeSetParams) (*Sessi if err != nil { return nil, err } - var result SessionModeSetResult + var result ModeSetResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1256,20 +1364,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 @@ -1278,20 +1386,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 } @@ -1300,20 +1408,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 @@ -1322,14 +1430,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 @@ -1339,7 +1447,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 } @@ -1349,7 +1457,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 { @@ -1360,7 +1468,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 } @@ -1370,33 +1478,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 @@ -1405,33 +1513,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 } @@ -1441,20 +1549,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 @@ -1463,14 +1571,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 @@ -1479,20 +1587,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 } @@ -1502,20 +1610,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 @@ -1524,14 +1632,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 @@ -1540,20 +1648,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 } @@ -1563,13 +1671,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 } @@ -1579,20 +1687,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 @@ -1601,14 +1709,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 @@ -1617,20 +1725,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 } @@ -1639,7 +1747,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 @@ -1654,7 +1762,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 } @@ -1663,7 +1771,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 @@ -1675,7 +1783,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 } @@ -1684,7 +1792,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 @@ -1694,14 +1802,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 @@ -1711,7 +1819,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 } @@ -1720,7 +1828,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 @@ -1730,7 +1838,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 } @@ -1739,7 +1847,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 @@ -1754,14 +1862,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 @@ -1773,7 +1881,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 } @@ -1783,20 +1891,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 @@ -1805,7 +1913,23 @@ 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 + } + return &result, nil +} + +// Experimental: UsageApi contains experimental APIs that may change or be removed. +type UsageApi sessionApi + +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 UsageMetrics if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -1832,9 +1956,10 @@ type SessionRpc struct { Permissions *PermissionsApi Shell *ShellApi History *HistoryApi + 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 @@ -1852,7 +1977,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 } @@ -1878,20 +2003,21 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { r.Permissions = (*PermissionsApi)(&r.common) r.Shell = (*ShellApi)(&r.common) r.History = (*HistoryApi)(&r.common) + r.Usage = (*UsageApi)(&r.common) return r } 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. @@ -1913,7 +2039,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)} } @@ -1932,7 +2058,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)} } @@ -1946,7 +2072,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)} } @@ -1960,7 +2086,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)} } @@ -1979,7 +2105,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)} } @@ -1998,7 +2124,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)} } @@ -2012,7 +2138,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)} } @@ -2031,7 +2157,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)} } @@ -2050,7 +2176,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)} } @@ -2064,7 +2190,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..cd7352b17 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.UIElicitationSchemaPropertyStringFormatDetails(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 d80a80f54..a2d66b42b 100644 --- a/go/types.go +++ b/go/types.go @@ -446,7 +446,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 753a6a65f..e0d591d98 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -20,7 +20,7 @@ export interface PingResult { protocolVersion: number; } -export interface PingParams { +export interface PingRequest { /** * Optional message to echo back */ @@ -40,7 +40,58 @@ export interface ModelsListResult { * Display name */ name: string; - capabilities: ModelCapabilities; + /** + * Model capabilities and limits + */ + capabilities: { + /** + * Feature flags indicating what the model supports + */ + supports: { + /** + * 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 + */ + 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; + }; + }; + }; /** * Policy state (if applicable) */ @@ -73,61 +124,6 @@ export interface ModelsListResult { defaultReasoningEffort?: string; }[]; } -/** - * 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 - */ - 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; - /** - * Maximum image size in bytes - */ - max_prompt_image_size: number; -} export interface ToolsListResult { /** @@ -159,7 +155,7 @@ export interface ToolsListResult { }[]; } -export interface ToolsListParams { +export interface ToolsListRequest { /** * Optional model ID — when provided, the returned tool list reflects model-specific overrides */ @@ -252,7 +248,7 @@ export interface McpConfigListResult { }; } -export interface McpConfigAddParams { +export interface McpConfigAddRequest { /** * Unique name for the MCP server */ @@ -303,7 +299,7 @@ export interface McpConfigAddParams { }; } -export interface McpConfigUpdateParams { +export interface McpConfigUpdateRequest { /** * Name of the MCP server to update */ @@ -354,7 +350,7 @@ export interface McpConfigUpdateParams { }; } -export interface McpConfigRemoveParams { +export interface McpConfigRemoveRequest { /** * Name of the MCP server to remove */ @@ -368,7 +364,7 @@ export interface SessionFsSetProviderResult { success: boolean; } -export interface SessionFsSetProviderParams { +export interface SessionFsSetProviderRequest { /** * Initial working directory for sessions */ @@ -383,26 +379,6 @@ export interface SessionFsSetProviderParams { conventions: "windows" | "posix"; } -/** @experimental */ -export interface SessionsForkResult { - /** - * The new forked session's ID - */ - sessionId: string; -} - -/** @experimental */ -export interface SessionsForkParams { - /** - * Source session ID to fork from - */ - sessionId: string; - /** - * Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. - */ - toEventId?: string; -} - export interface SessionModelGetCurrentResult { /** * Currently active model identifier @@ -410,7 +386,7 @@ export interface SessionModelGetCurrentResult { modelId?: string; } -export interface SessionModelGetCurrentParams { +export interface SessionModelGetCurrentRequest { /** * Target session identifier */ @@ -424,7 +400,7 @@ export interface SessionModelSwitchToResult { modelId?: string; } -export interface SessionModelSwitchToParams { +export interface SessionModelSwitchToRequest { /** * Target session identifier */ @@ -437,47 +413,43 @@ export interface SessionModelSwitchToParams { * Reasoning effort level to use for the model */ reasoningEffort?: string; - modelCapabilities?: ModelCapabilitiesOverride; -} -/** - * 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 + * Override individual model capabilities resolved by the runtime */ - max_prompt_images?: number; - /** - * Maximum image size in bytes - */ - max_prompt_image_size?: number; + modelCapabilities?: { + /** + * Feature flags indicating what the model supports + */ + supports?: { + vision?: boolean; + reasoningEffort?: boolean; + }; + /** + * Token limits for prompts, outputs, and context window + */ + 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 { @@ -487,7 +459,7 @@ export interface SessionModeGetResult { mode: "interactive" | "plan" | "autopilot"; } -export interface SessionModeGetParams { +export interface SessionModeGetRequest { /** * Target session identifier */ @@ -501,7 +473,7 @@ export interface SessionModeSetResult { mode: "interactive" | "plan" | "autopilot"; } -export interface SessionModeSetParams { +export interface SessionModeSetRequest { /** * Target session identifier */ @@ -527,7 +499,7 @@ export interface SessionPlanReadResult { path: string | null; } -export interface SessionPlanReadParams { +export interface SessionPlanReadRequest { /** * Target session identifier */ @@ -536,7 +508,7 @@ export interface SessionPlanReadParams { export interface SessionPlanUpdateResult {} -export interface SessionPlanUpdateParams { +export interface SessionPlanUpdateRequest { /** * Target session identifier */ @@ -549,7 +521,7 @@ export interface SessionPlanUpdateParams { export interface SessionPlanDeleteResult {} -export interface SessionPlanDeleteParams { +export interface SessionPlanDeleteRequest { /** * Target session identifier */ @@ -563,7 +535,7 @@ export interface SessionWorkspaceListFilesResult { files: string[]; } -export interface SessionWorkspaceListFilesParams { +export interface SessionWorkspaceListFilesRequest { /** * Target session identifier */ @@ -577,7 +549,7 @@ export interface SessionWorkspaceReadFileResult { content: string; } -export interface SessionWorkspaceReadFileParams { +export interface SessionWorkspaceReadFileRequest { /** * Target session identifier */ @@ -590,7 +562,7 @@ export interface SessionWorkspaceReadFileParams { export interface SessionWorkspaceCreateFileResult {} -export interface SessionWorkspaceCreateFileParams { +export interface SessionWorkspaceCreateFileRequest { /** * Target session identifier */ @@ -614,7 +586,7 @@ export interface SessionFleetStartResult { } /** @experimental */ -export interface SessionFleetStartParams { +export interface SessionFleetStartRequest { /** * Target session identifier */ @@ -647,7 +619,7 @@ export interface SessionAgentListResult { } /** @experimental */ -export interface SessionAgentListParams { +export interface SessionAgentListRequest { /** * Target session identifier */ @@ -676,7 +648,7 @@ export interface SessionAgentGetCurrentResult { } /** @experimental */ -export interface SessionAgentGetCurrentParams { +export interface SessionAgentGetCurrentRequest { /** * Target session identifier */ @@ -705,7 +677,7 @@ export interface SessionAgentSelectResult { } /** @experimental */ -export interface SessionAgentSelectParams { +export interface SessionAgentSelectRequest { /** * Target session identifier */ @@ -720,7 +692,7 @@ export interface SessionAgentSelectParams { export interface SessionAgentDeselectResult {} /** @experimental */ -export interface SessionAgentDeselectParams { +export interface SessionAgentDeselectRequest { /** * Target session identifier */ @@ -749,7 +721,7 @@ export interface SessionAgentReloadResult { } /** @experimental */ -export interface SessionAgentReloadParams { +export interface SessionAgentReloadRequest { /** * Target session identifier */ @@ -790,7 +762,7 @@ export interface SessionSkillsListResult { } /** @experimental */ -export interface SessionSkillsListParams { +export interface SessionSkillsListRequest { /** * Target session identifier */ @@ -801,7 +773,7 @@ export interface SessionSkillsListParams { export interface SessionSkillsEnableResult {} /** @experimental */ -export interface SessionSkillsEnableParams { +export interface SessionSkillsEnableRequest { /** * Target session identifier */ @@ -816,7 +788,7 @@ export interface SessionSkillsEnableParams { export interface SessionSkillsDisableResult {} /** @experimental */ -export interface SessionSkillsDisableParams { +export interface SessionSkillsDisableRequest { /** * Target session identifier */ @@ -831,7 +803,7 @@ export interface SessionSkillsDisableParams { export interface SessionSkillsReloadResult {} /** @experimental */ -export interface SessionSkillsReloadParams { +export interface SessionSkillsReloadRequest { /** * Target session identifier */ @@ -864,7 +836,7 @@ export interface SessionMcpListResult { } /** @experimental */ -export interface SessionMcpListParams { +export interface SessionMcpListRequest { /** * Target session identifier */ @@ -875,7 +847,7 @@ export interface SessionMcpListParams { export interface SessionMcpEnableResult {} /** @experimental */ -export interface SessionMcpEnableParams { +export interface SessionMcpEnableRequest { /** * Target session identifier */ @@ -890,7 +862,7 @@ export interface SessionMcpEnableParams { export interface SessionMcpDisableResult {} /** @experimental */ -export interface SessionMcpDisableParams { +export interface SessionMcpDisableRequest { /** * Target session identifier */ @@ -905,7 +877,7 @@ export interface SessionMcpDisableParams { export interface SessionMcpReloadResult {} /** @experimental */ -export interface SessionMcpReloadParams { +export interface SessionMcpReloadRequest { /** * Target session identifier */ @@ -938,7 +910,7 @@ export interface SessionPluginsListResult { } /** @experimental */ -export interface SessionPluginsListParams { +export interface SessionPluginsListRequest { /** * Target session identifier */ @@ -975,7 +947,7 @@ export interface SessionExtensionsListResult { } /** @experimental */ -export interface SessionExtensionsListParams { +export interface SessionExtensionsListRequest { /** * Target session identifier */ @@ -986,7 +958,7 @@ export interface SessionExtensionsListParams { export interface SessionExtensionsEnableResult {} /** @experimental */ -export interface SessionExtensionsEnableParams { +export interface SessionExtensionsEnableRequest { /** * Target session identifier */ @@ -1001,7 +973,7 @@ export interface SessionExtensionsEnableParams { export interface SessionExtensionsDisableResult {} /** @experimental */ -export interface SessionExtensionsDisableParams { +export interface SessionExtensionsDisableRequest { /** * Target session identifier */ @@ -1016,7 +988,31 @@ export interface SessionExtensionsDisableParams { export interface SessionExtensionsReloadResult {} /** @experimental */ -export interface SessionExtensionsReloadParams { +export interface SessionExtensionsReloadRequest { + /** + * Target session identifier + */ + sessionId: string; +} + +/** @experimental */ +export interface SessionCompactionCompactResult { + /** + * Whether compaction completed successfully + */ + success: boolean; + /** + * Number of tokens freed by compaction + */ + tokensRemoved: number; + /** + * Number of messages removed during compaction + */ + messagesRemoved: number; +} + +/** @experimental */ +export interface SessionCompactionCompactRequest { /** * Target session identifier */ @@ -1030,7 +1026,7 @@ export interface SessionToolsHandlePendingToolCallResult { success: boolean; } -export interface SessionToolsHandlePendingToolCallParams { +export interface SessionToolsHandlePendingToolCallRequest { /** * Target session identifier */ @@ -1053,7 +1049,7 @@ export interface SessionCommandsHandlePendingCommandResult { success: boolean; } -export interface SessionCommandsHandlePendingCommandParams { +export interface SessionCommandsHandlePendingCommandRequest { /** * Target session identifier */ @@ -1081,7 +1077,7 @@ export interface SessionUiElicitationResult { }; } -export interface SessionUiElicitationParams { +export interface SessionUiElicitationRequest { /** * Target session identifier */ @@ -1105,7 +1101,6 @@ export interface SessionUiElicitationParams { [k: string]: | { type: "string"; - title?: string; description?: string; enum: string[]; enumNames?: string[]; @@ -1113,17 +1108,14 @@ export interface SessionUiElicitationParams { } | { type: "string"; - title?: string; description?: string; oneOf: { const: string; - title: string; }[]; default?: string; } | { type: "array"; - title?: string; description?: string; minItems?: number; maxItems?: number; @@ -1135,27 +1127,23 @@ export interface SessionUiElicitationParams { } | { type: "array"; - title?: string; description?: string; minItems?: number; maxItems?: number; items: { anyOf: { const: string; - title: string; }[]; }; default?: string[]; } | { type: "boolean"; - title?: string; description?: string; default?: boolean; } | { type: "string"; - title?: string; description?: string; minLength?: number; maxLength?: number; @@ -1164,7 +1152,6 @@ export interface SessionUiElicitationParams { } | { type: "number" | "integer"; - title?: string; description?: string; minimum?: number; maximum?: number; @@ -1185,7 +1172,7 @@ export interface SessionUiHandlePendingElicitationResult { success: boolean; } -export interface SessionUiHandlePendingElicitationParams { +export interface SessionUiHandlePendingElicitationRequest { /** * Target session identifier */ @@ -1218,7 +1205,7 @@ export interface SessionPermissionsHandlePendingPermissionRequestResult { success: boolean; } -export interface SessionPermissionsHandlePendingPermissionRequestParams { +export interface SessionPermissionsHandlePendingPermissionRequestRequest { /** * Target session identifier */ @@ -1258,7 +1245,7 @@ export interface SessionLogResult { eventId: string; } -export interface SessionLogParams { +export interface SessionLogRequest { /** * Target session identifier */ @@ -1288,7 +1275,7 @@ export interface SessionShellExecResult { processId: string; } -export interface SessionShellExecParams { +export interface SessionShellExecRequest { /** * Target session identifier */ @@ -1314,7 +1301,7 @@ export interface SessionShellKillResult { killed: boolean; } -export interface SessionShellKillParams { +export interface SessionShellKillRequest { /** * Target session identifier */ @@ -1329,50 +1316,6 @@ export interface SessionShellKillParams { signal?: "SIGTERM" | "SIGKILL" | "SIGINT"; } -/** @experimental */ -export interface SessionHistoryCompactResult { - /** - * Whether compaction completed successfully - */ - success: boolean; - /** - * Number of tokens freed by compaction - */ - tokensRemoved: number; - /** - * Number of messages removed during compaction - */ - messagesRemoved: number; -} - -/** @experimental */ -export interface SessionHistoryCompactParams { - /** - * Target session identifier - */ - sessionId: string; -} - -/** @experimental */ -export interface SessionHistoryTruncateResult { - /** - * Number of events that were removed - */ - eventsRemoved: number; -} - -/** @experimental */ -export interface SessionHistoryTruncateParams { - /** - * Target session identifier - */ - sessionId: string; - /** - * Event ID to truncate to. This event and all events after it are removed from the session. - */ - eventId: string; -} - export interface SessionFsReadFileResult { /** * File content as UTF-8 string @@ -1380,7 +1323,7 @@ export interface SessionFsReadFileResult { content: string; } -export interface SessionFsReadFileParams { +export interface SessionFsReadFileRequest { /** * Target session identifier */ @@ -1391,7 +1334,7 @@ export interface SessionFsReadFileParams { path: string; } -export interface SessionFsWriteFileParams { +export interface SessionFsWriteFileRequest { /** * Target session identifier */ @@ -1410,7 +1353,7 @@ export interface SessionFsWriteFileParams { mode?: number; } -export interface SessionFsAppendFileParams { +export interface SessionFsAppendFileRequest { /** * Target session identifier */ @@ -1436,7 +1379,7 @@ export interface SessionFsExistsResult { exists: boolean; } -export interface SessionFsExistsParams { +export interface SessionFsExistsRequest { /** * Target session identifier */ @@ -1470,7 +1413,7 @@ export interface SessionFsStatResult { birthtime: string; } -export interface SessionFsStatParams { +export interface SessionFsStatRequest { /** * Target session identifier */ @@ -1481,7 +1424,7 @@ export interface SessionFsStatParams { path: string; } -export interface SessionFsMkdirParams { +export interface SessionFsMkdirRequest { /** * Target session identifier */ @@ -1507,7 +1450,7 @@ export interface SessionFsReaddirResult { entries: string[]; } -export interface SessionFsReaddirParams { +export interface SessionFsReaddirRequest { /** * Target session identifier */ @@ -1534,7 +1477,7 @@ export interface SessionFsReaddirWithTypesResult { }[]; } -export interface SessionFsReaddirWithTypesParams { +export interface SessionFsReaddirWithTypesRequest { /** * Target session identifier */ @@ -1545,7 +1488,7 @@ export interface SessionFsReaddirWithTypesParams { path: string; } -export interface SessionFsRmParams { +export interface SessionFsRmRequest { /** * Target session identifier */ @@ -1564,7 +1507,7 @@ export interface SessionFsRmParams { force?: boolean; } -export interface SessionFsRenameParams { +export interface SessionFsRenameRequest { /** * Target session identifier */ @@ -1582,14 +1525,14 @@ 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 => connection.sendRequest("models.list", {}), }, tools: { - list: async (params: ToolsListParams): Promise => + list: async (params: ToolsListRequest): Promise => connection.sendRequest("tools.list", params), }, account: { @@ -1600,23 +1543,18 @@ export function createServerRpc(connection: MessageConnection) { config: { 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), }, }, sessionFs: { - setProvider: async (params: SessionFsSetProviderParams): Promise => + setProvider: async (params: SessionFsSetProviderRequest): Promise => connection.sendRequest("sessionFs.setProvider", params), }, - /** @experimental */ - sessions: { - fork: async (params: SessionsForkParams): Promise => - connection.sendRequest("sessions.fork", params), - }, }; } @@ -1626,19 +1564,19 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin model: { 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 => 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 => 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 => connection.sendRequest("session.plan.delete", { sessionId }), @@ -1646,14 +1584,14 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin workspace: { 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 */ @@ -1662,7 +1600,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.agent.list", { sessionId }), 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 => connection.sendRequest("session.agent.deselect", { sessionId }), @@ -1673,9 +1611,9 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin skills: { 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 => connection.sendRequest("session.skills.reload", { sessionId }), @@ -1684,9 +1622,9 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin mcp: { 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 => connection.sendRequest("session.mcp.reload", { sessionId }), @@ -1700,61 +1638,59 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin extensions: { 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 => connection.sendRequest("session.extensions.reload", { sessionId }), }, + /** @experimental */ + compaction: { + compact: async (): Promise => + connection.sendRequest("session.compaction.compact", { 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 => - connection.sendRequest("session.history.compact", { sessionId }), - truncate: async (params: Omit): Promise => - connection.sendRequest("session.history.truncate", { sessionId, ...params }), - }, }; } /** 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. */ @@ -1772,52 +1708,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 e9bc2a550..9f7e23876 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -270,7 +270,7 @@ export type SessionEvent = ephemeral: true; type: "session.idle"; /** - * Payload indicating the session is idle with no background agents in flight + * Payload indicating the session is fully idle with no background tasks in flight */ data: { /** @@ -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: {}; } | { /** @@ -508,6 +503,248 @@ export type SessionEvent = operation: "create" | "update"; }; } + | { + /** + * Unique event identifier (UUID v4), generated when the event is emitted + */ + id: string; + /** + * ISO 8601 timestamp when the event was created + */ + timestamp: string; + /** + * ID of the chronologically preceding event in the session, forming a linked chain. Null for the first event. + */ + parentId: string | null; + /** + * When true, the event is transient and not persisted to the session event log on disk + */ + ephemeral?: boolean; + type: "session.import_legacy"; + /** + * Legacy session import data including the complete session JSON, import timestamp, and source file path + */ + data: { + legacySession: { + sessionId: string; + startTime: string; + chatMessages: ( + | { + content: + | string + | { + type: "text"; + text: string; + }[]; + role: "developer"; + name?: string; + } + | { + content: + | string + | { + type: "text"; + text: string; + }[]; + role: "system"; + name?: string; + } + | { + content: + | string + | ( + | { + type: "text"; + text: string; + } + | { + type: "image_url"; + image_url: { + url: string; + detail?: "auto" | "low" | "high"; + }; + } + | { + type: "input_audio"; + input_audio: { + data: string; + format: "wav" | "mp3"; + }; + } + | { + type: "file"; + file: { + file_date?: string; + file_id?: string; + filename?: string; + }; + } + )[]; + role: "user"; + name?: string; + } + | { + content?: + | ( + | string + | ( + | { + type: "text"; + text: string; + } + | { + type: "refusal"; + refusal: string; + } + )[] + ) + | null; + role: "assistant"; + name?: string; + refusal?: string | null; + audio?: { + id: string; + } | null; + function_call?: { + name: string; + arguments: string; + } | null; + tool_calls?: ( + | { + id: string; + type: "function"; + function: { + name: string; + arguments: string; + }; + } + | { + id: string; + type: "custom"; + custom: { + name: string; + input: string; + }; + } + )[]; + } + | { + content: + | string + | { + type: "text"; + text: string; + }[]; + role: "tool"; + tool_call_id: string; + } + | { + content: string | null; + role: "function"; + name: string; + } + )[]; + timeline: (( + | { + type: "copilot"; + text: string; + isStreaming?: boolean; + } + | { + type: "error"; + text: string; + } + | { + type: "info"; + text: string; + } + | { + type: "warning"; + text: string; + } + | { + type: "user"; + text: string; + } + | { + type: "tool_call_requested"; + callId: string; + name: string; + toolTitle?: string; + mcpServerName?: string; + intentionSummary: string | null; + arguments?: unknown; + partialOutput?: string; + isHidden?: boolean; + isAlwaysExpanded?: boolean; + showNoContent?: boolean; + } + | { + type: "tool_call_completed"; + callId: string; + name: string; + toolTitle?: string; + mcpServerName?: string; + intentionSummary: string | null; + result: + | { + type: "success"; + log: string; + detailedLog?: string; + markdown?: boolean; + } + | { + type: "failure"; + log: string; + markdown?: boolean; + } + | { + type: "rejected"; + markdown?: boolean; + } + | { + type: "denied"; + log: string; + markdown?: boolean; + }; + arguments?: unknown; + isHidden?: boolean; + isAlwaysExpanded?: boolean; + showNoContent?: boolean; + } + ) & { + id: string; + timestamp: string; + })[]; + selectedModel?: + | "claude-sonnet-4.6" + | "claude-sonnet-4.5" + | "claude-haiku-4.5" + | "claude-opus-4.6" + | "claude-opus-4.6-fast" + | "claude-opus-4.6-1m" + | "claude-opus-4.5" + | "claude-sonnet-4" + | "goldeneye" + | "gpt-5.4" + | "gpt-5.3-codex" + | "gpt-5.2-codex" + | "gpt-5.2" + | "gpt-5.1" + | "gpt-5.4-mini" + | "gpt-5-mini" + | "gpt-4.1"; + }; + /** + * ISO 8601 timestamp when the import was performed + */ + importTime: string; + /** + * File path of the legacy session file that was imported + */ + sourceFile: string; + }; + } | { /** * Unique event identifier (UUID v4), generated when the event is emitted @@ -649,7 +886,7 @@ export type SessionEvent = */ data: { /** - * Event ID that was rewound to; this event and all after it were removed + * Event ID that was rewound to; all events after this one were removed */ upToEventId: string; /** @@ -1176,10 +1413,6 @@ export type SessionEvent = * Issue, pull request, or discussion number */ number: number; - /** - * Title of the referenced item - */ - title: string; /** * Type of GitHub reference */ @@ -1478,10 +1711,6 @@ export type SessionEvent = * CAPI interaction ID for correlating this message with upstream telemetry */ interactionId?: string; - /** - * GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs - */ - requestId?: string; /** * Tool call ID of the parent tool invocation when this event originates from a sub-agent */ @@ -2009,10 +2238,6 @@ export type SessionEvent = * Resource name identifier */ name: string; - /** - * Human-readable display title for the resource - */ - title?: string; /** * URI identifying the resource */ diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts index 13367631f..923ec1531 100644 --- a/nodejs/src/types.ts +++ b/nodejs/src/types.ts @@ -649,11 +649,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/python/copilot/client.py b/python/copilot/client.py index 8be8b8220..3d0761f8d 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 @@ -1776,9 +1777,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 43bb879be..927421e7e 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -18,31 +18,25 @@ from enum import Enum from uuid import UUID - 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)) 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,37 +45,30 @@ def from_union(fs, x): pass assert False - 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 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 @@ -108,17 +95,16 @@ def to_dict(self) -> dict: result["timestamp"] = to_float(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,26 +112,24 @@ 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""" @@ -174,7 +158,6 @@ def to_dict(self) -> dict: 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""" @@ -189,7 +172,6 @@ class ModelCapabilitiesLimits: """Maximum number of prompt/input tokens""" vision: ModelCapabilitiesLimitsVision | None = None - """Vision-specific limits""" @staticmethod def from_dict(obj: Any) -> 'ModelCapabilitiesLimits': @@ -211,7 +193,6 @@ def to_dict(self) -> dict: 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 +218,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 +238,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 +249,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 +261,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 +284,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 +296,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 +361,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,9 +396,8 @@ def to_dict(self) -> dict: result["model"] = from_union([from_str, from_none], self.model) return result - @dataclass -class QuotaSnapshot: +class AccountQuotaSnapshot: entitlement_requests: float """Number of requests included in the entitlement""" @@ -453,7 +417,7 @@ class QuotaSnapshot: """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")) @@ -461,7 +425,7 @@ def from_dict(obj: Any) -> 'QuotaSnapshot': 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) + return AccountQuotaSnapshot(entitlement_requests, overage, overage_allowed_with_exhausted_quota, remaining_percentage, used_requests, reset_date) def to_dict(self) -> dict: result: dict = {} @@ -474,74 +438,70 @@ def to_dict(self) -> dict: result["resetDate"] = from_union([from_str, 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 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")) 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,7 +514,7 @@ 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: @@ -562,7 +522,7 @@ def to_dict(self) -> dict: 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 +533,59 @@ 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 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")) 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,7 +598,7 @@ 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: @@ -648,7 +606,7 @@ def to_dict(self) -> dict: 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 +617,62 @@ 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 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")) 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,7 +685,7 @@ 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: @@ -739,7 +693,7 @@ def to_dict(self) -> dict: 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,45 +704,111 @@ 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 MCPConfigRemoveRequest(name) + + def to_dict(self) -> dict: + result: dict = {} + result["name"] = from_str(self.name) + return result + +class DiscoveredMCPServerSource(Enum): + """Configuration source""" + + BUILTIN = "builtin" + PLUGIN = "plugin" + USER = "user" + WORKSPACE = "workspace" + +@dataclass +class DiscoveredMCPServer: + enabled: bool + """Whether the server is enabled (not in the disabled list)""" + + name: str + """Server name (config key)""" + + source: DiscoveredMCPServerSource + type: str | None = None + """Server type: local, stdio, http, or sse""" + + @staticmethod + def from_dict(obj: Any) -> 'DiscoveredMCPServer': assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) name = from_str(obj.get("name")) - return MCPConfigRemoveParams(name) + source = DiscoveredMCPServerSource(obj.get("source")) + type = from_union([from_str, 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(DiscoveredMCPServerSource, self.source) + if self.type is not None: + result["type"] = from_union([from_str, from_none], self.type) + return result + +@dataclass +class MCPDiscoverResult: + servers: list[DiscoveredMCPServer] + """MCP servers discovered from all sources""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPDiscoverResult': + assert isinstance(obj, dict) + servers = from_list(DiscoveredMCPServer.from_dict, obj.get("servers")) + return MCPDiscoverResult(servers) + + def to_dict(self) -> dict: + result: dict = {} + result["servers"] = from_list(lambda x: to_class(DiscoveredMCPServer, x), self.servers) return result +@dataclass +class MCPDiscoverRequest: + working_directory: str | None = None + """Working directory used as context for discovery (e.g., plugin resolution)""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPDiscoverRequest': + assert isinstance(obj, dict) + working_directory = from_union([from_str, from_none], obj.get("workingDirectory")) + return MCPDiscoverRequest(working_directory) + + def to_dict(self) -> dict: + result: dict = {} + if self.working_directory is not None: + result["workingDirectory"] = from_union([from_str, from_none], self.working_directory) + return result @dataclass class SessionFSSetProviderResult: @@ -806,19 +826,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""" @@ -826,21 +842,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: @@ -858,10 +873,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""" @@ -871,11 +885,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 = {} @@ -884,17 +898,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 = {} @@ -902,17 +915,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 = {} @@ -920,7 +932,6 @@ 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 @@ -950,7 +961,6 @@ def to_dict(self) -> dict: 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""" @@ -983,7 +993,6 @@ def to_dict(self) -> dict: 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""" @@ -1006,16 +1015,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': @@ -1032,25 +1037,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 = {} @@ -1061,72 +1063,60 @@ def to_dict(self) -> dict: result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort) return result +class SessionMode(Enum): + """The current 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.""" +class ModeGetResult: + mode: SessionMode @staticmethod - def from_dict(obj: Any) -> 'SessionModeGetResult': + def from_dict(obj: Any) -> 'ModeGetResult': assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeGetResult(mode) + mode = SessionMode(obj.get("mode")) + return ModeGetResult(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 SessionModeSetResult: - mode: Mode - """The agent mode after switching.""" +class ModeSetResult: + mode: SessionMode @staticmethod - def from_dict(obj: Any) -> 'SessionModeSetResult': + def from_dict(obj: Any) -> 'ModeSetResult': assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeSetResult(mode) + mode = SessionMode(obj.get("mode")) + return ModeSetResult(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".""" +class ModeSetRequest: + mode: SessionMode @staticmethod - def from_dict(obj: Any) -> 'SessionModeSetParams': + def from_dict(obj: Any) -> 'ModeSetRequest': assert isinstance(obj, dict) - mode = Mode(obj.get("mode")) - return SessionModeSetParams(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 SessionPlanReadResult: +class Plan: exists: bool """Whether the plan file exists in the workspace""" @@ -1137,12 +1127,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 = {} @@ -1151,113 +1141,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""" @@ -1265,11 +1247,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 = {} @@ -1277,36 +1259,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 = {} @@ -1314,9 +1294,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""" @@ -1327,12 +1306,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 = {} @@ -1341,27 +1320,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""" @@ -1372,12 +1349,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 = {} @@ -1386,27 +1363,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 @@ -1419,12 +1394,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 = {} @@ -1433,58 +1408,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""" @@ -1495,12 +1465,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 = {} @@ -1509,25 +1479,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 @@ -1570,101 +1538,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" @@ -1674,15 +1635,12 @@ 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""" @@ -1690,112 +1648,105 @@ class ServerElement: """Configuration source: user, workspace, plugin, or builtin""" @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) + 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) 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 @@ -1828,32 +1779,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 Source(Enum): +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""" @@ -1862,7 +1810,6 @@ class ExtensionStatus(Enum): RUNNING = "running" STARTING = "starting" - @dataclass class Extension: id: str @@ -1871,12 +1818,8 @@ class Extension: name: str """Extension name (directory name)""" - source: Source - """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" - + source: ExtensionSource status: ExtensionStatus - """Current status: running, disabled, failed, or starting""" - pid: int | None = None """Process ID if the extension is running""" @@ -1885,7 +1828,7 @@ def from_dict(obj: Any) -> 'Extension': assert isinstance(obj, dict) id = from_str(obj.get("id")) name = from_str(obj.get("name")) - source = Source(obj.get("source")) + source = ExtensionSource(obj.get("source")) status = ExtensionStatus(obj.get("status")) pid = from_union([from_int, from_none], obj.get("pid")) return Extension(id, name, source, status, pid) @@ -1894,138 +1837,137 @@ 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["source"] = to_enum(ExtensionSource, self.source) result["status"] = to_enum(ExtensionStatus, self.status) if self.pid is not None: 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""" + error: str | None = None + """Error message if the tool call failed""" + result_type: str | None = None + """Type of the tool result""" + tool_telemetry: dict[str, Any] | None = None + """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 = {} @@ -2038,20 +1980,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 - result: ResultResult | str | None = None + """Error message if the tool call failed""" + + 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 = {} @@ -2059,28 +2004,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""" @@ -2088,11 +2032,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 = {} @@ -2101,56 +2045,52 @@ def to_dict(self) -> dict: result["error"] = from_union([from_str, from_none], self.error) return result - -class Action(Enum): +class UIElicitationAction(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: UIElicitationAction 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 = UIElicitationAction(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(UIElicitationAction, 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 = {} @@ -2158,24 +2098,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 = {} @@ -2184,21 +2122,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 = {} @@ -2206,56 +2143,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: @@ -2267,15 +2202,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: @@ -2286,16 +2221,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 @@ -2305,127 +2238,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" @@ -2434,18 +2335,40 @@ 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 + + Denied because approval rules explicitly blocked it + + Denied because no approval rule matched and user confirmation was unavailable + + Denied by the user during an interactive prompt + + Denied by the organization's content exclusion policy + + Denied by a permission request hook registered by an extension or plugin + """ rules: list[Any] | None = None + """Rules that denied the request""" + feedback: str | None = None + """Optional feedback from the user explaining the denial""" + message: str | None = None + """Human-readable explanation of why the path was excluded + + Optional message from the hook explaining the denial + """ path: str | None = None + """File path that triggered the exclusion""" + interrupt: bool | None = None + """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")) @@ -2453,7 +2376,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 = {} @@ -2470,44 +2393,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 - result: SessionPermissionsHandlePendingPermissionRequestParamsResult + """Request ID of the pending permission request""" + + 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". """ @@ -2515,30 +2437,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 = {} @@ -2546,31 +2464,29 @@ 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""" @@ -2581,12 +2497,12 @@ class SessionShellExecParams: """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) + return ShellExecRequest(command, cwd, timeout) def to_dict(self) -> dict: result: dict = {} @@ -2597,58 +2513,99 @@ def to_dict(self) -> dict: result["timeout"] = from_union([to_float, 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 HistoryCompactContextWindow: + """Post-compaction context window usage breakdown""" + + current_tokens: float + """Current total tokens in the context window (system + conversation + tool definitions)""" + + messages_length: float + """Current number of messages in the conversation""" + + token_limit: float + """Maximum token count for the model's context window""" + + conversation_tokens: float | None = None + """Token count from non-system messages (user, assistant, tool)""" + + system_tokens: float | None = None + """Token count from system message(s)""" + + tool_definitions_tokens: float | None = None + """Token count from tool definitions""" + + @staticmethod + 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 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) + if self.conversation_tokens is not None: + result["conversationTokens"] = from_union([to_float, from_none], self.conversation_tokens) + if self.system_tokens is not None: + result["systemTokens"] = from_union([to_float, 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) + return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionHistoryCompactResult: +class HistoryCompact: messages_removed: float """Number of messages removed during compaction""" @@ -2658,57 +2615,224 @@ class SessionHistoryCompactResult: tokens_removed: float """Number of tokens freed by compaction""" + 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")) success = from_bool(obj.get("success")) tokens_removed = from_float(obj.get("tokensRemoved")) - return SessionHistoryCompactResult(messages_removed, success, tokens_removed) + 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["success"] = from_bool(self.success) result["tokensRemoved"] = to_float(self.tokens_removed) + if self.context_window is not None: + 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: +class HistoryTruncateResult: events_removed: float """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) + return HistoryTruncateResult(events_removed) def to_dict(self) -> dict: result: dict = {} result["eventsRemoved"] = to_float(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 UsageMetricsCodeChanges: + """Aggregated code change metrics""" + + files_modified_count: int + """Number of distinct files modified""" + + lines_added: int + """Total lines of code added""" + + lines_removed: int + """Total lines of code removed""" + + @staticmethod + 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 UsageMetricsCodeChanges(files_modified_count, lines_added, lines_removed) + + def to_dict(self) -> dict: + result: dict = {} + result["filesModifiedCount"] = from_int(self.files_modified_count) + result["linesAdded"] = from_int(self.lines_added) + result["linesRemoved"] = from_int(self.lines_removed) + return result + +@dataclass +class UsageMetricsModelMetricRequests: + """Request count and cost metrics for this model""" + + cost: float + """User-initiated premium request cost (with multiplier applied)""" + + count: int + """Number of API requests made with this model""" + + @staticmethod + def from_dict(obj: Any) -> 'UsageMetricsModelMetricRequests': + assert isinstance(obj, dict) + cost = from_float(obj.get("cost")) + count = from_int(obj.get("count")) + return UsageMetricsModelMetricRequests(cost, count) + + def to_dict(self) -> dict: + result: dict = {} + result["cost"] = to_float(self.cost) + result["count"] = from_int(self.count) + return result + +@dataclass +class UsageMetricsModelMetricUsage: + """Token usage metrics for this model""" + + cache_read_tokens: int + """Total tokens read from prompt cache""" + + cache_write_tokens: int + """Total tokens written to prompt cache""" + + input_tokens: int + """Total input tokens consumed""" + + output_tokens: int + """Total output tokens produced""" + + reasoning_tokens: int | None = None + """Total output tokens used for reasoning""" + + @staticmethod + 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")) + 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 = {} + result["cacheReadTokens"] = from_int(self.cache_read_tokens) + 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 UsageMetricsModelMetric: + requests: UsageMetricsModelMetricRequests + usage: UsageMetricsModelMetricUsage + + @staticmethod + def from_dict(obj: Any) -> 'UsageMetricsModelMetric': + assert isinstance(obj, dict) + 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(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 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, UsageMetricsModelMetric] + """Per-model token and request metrics, keyed by model identifier""" + + session_start_time: int + """Session start timestamp (epoch milliseconds)""" + + total_api_duration_ms: float + """Total time spent in model API calls (milliseconds)""" + + total_premium_request_cost: float + """Total user-initiated premium request cost across all models (may be fractional due to + multipliers) + """ + total_user_requests: int + """Raw count of user-initiated API requests""" + + current_model: str | None = None + """Currently active model identifier""" + + @staticmethod + def from_dict(obj: Any) -> 'UsageMetrics': + assert isinstance(obj, dict) + 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(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 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(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(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) + result["totalUserRequests"] = from_int(self.total_user_requests) + if self.current_model is not None: + result["currentModel"] = from_union([from_str, from_none], self.current_model) + return result @dataclass class SessionFSReadFileResult: @@ -2726,9 +2850,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""" @@ -2736,11 +2859,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 = {} @@ -2748,9 +2871,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""" @@ -2764,13 +2886,13 @@ class SessionFSWriteFileParams: """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) + return SessionFSWriteFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} @@ -2781,9 +2903,8 @@ def to_dict(self) -> dict: result["mode"] = from_union([to_float, from_none], self.mode) return result - @dataclass -class SessionFSAppendFileParams: +class SessionFSAppendFileRequest: content: str """Content to append""" @@ -2797,13 +2918,13 @@ class SessionFSAppendFileParams: """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) + return SessionFSAppendFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} @@ -2814,7 +2935,6 @@ def to_dict(self) -> dict: result["mode"] = from_union([to_float, from_none], self.mode) return result - @dataclass class SessionFSExistsResult: exists: bool @@ -2831,9 +2951,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""" @@ -2841,11 +2960,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 = {} @@ -2853,7 +2972,6 @@ def to_dict(self) -> dict: result["sessionId"] = from_str(self.session_id) return result - @dataclass class SessionFSStatResult: birthtime: str @@ -2890,9 +3008,8 @@ def to_dict(self) -> dict: result["size"] = to_float(self.size) return result - @dataclass -class SessionFSStatParams: +class SessionFSStatRequest: path: str """Path using SessionFs conventions""" @@ -2900,11 +3017,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 = {} @@ -2912,9 +3029,8 @@ 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""" @@ -2928,13 +3044,13 @@ class SessionFSMkdirParams: """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")) 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 = {} @@ -2946,7 +3062,6 @@ def to_dict(self) -> dict: result["recursive"] = from_union([from_bool, from_none], self.recursive) return result - @dataclass class SessionFSReaddirResult: entries: list[str] @@ -2963,9 +3078,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""" @@ -2973,11 +3087,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 = {} @@ -2985,55 +3099,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""" @@ -3041,11 +3150,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 = {} @@ -3053,9 +3162,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""" @@ -3069,13 +3177,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 = {} @@ -3087,9 +3195,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""" @@ -3100,12 +3207,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 = {} @@ -3114,725 +3221,563 @@ 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_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_config_remove_params_from_dict(s: Any) -> MCPConfigRemoveParams: - return MCPConfigRemoveParams.from_dict(s) +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_config_remove_params_to_dict(x: MCPConfigRemoveParams) -> Any: - return to_class(MCPConfigRemoveParams, x) +def mcp_discover_request_from_dict(s: Any) -> MCPDiscoverRequest: + return MCPDiscoverRequest.from_dict(s) +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 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_plan_read_result_to_dict(x: SessionPlanReadResult) -> Any: - return to_class(SessionPlanReadResult, 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_plan_update_result_from_dict(s: Any) -> SessionPlanUpdateResult: - return SessionPlanUpdateResult.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_plan_update_result_to_dict(x: SessionPlanUpdateResult) -> Any: - return to_class(SessionPlanUpdateResult, x) +def model_switch_to_request_to_dict(x: ModelSwitchToRequest) -> Any: + return to_class(ModelSwitchToRequest, x) +def mode_get_result_from_dict(s: Any) -> ModeGetResult: + return ModeGetResult.from_dict(s) -def session_plan_update_params_from_dict(s: Any) -> SessionPlanUpdateParams: - return SessionPlanUpdateParams.from_dict(s) +def mode_get_result_to_dict(x: ModeGetResult) -> Any: + return to_class(ModeGetResult, x) +def mode_set_result_from_dict(s: Any) -> ModeSetResult: + return ModeSetResult.from_dict(s) -def session_plan_update_params_to_dict(x: SessionPlanUpdateParams) -> Any: - return to_class(SessionPlanUpdateParams, x) +def mode_set_result_to_dict(x: ModeSetResult) -> Any: + return to_class(ModeSetResult, x) +def mode_set_request_from_dict(s: Any) -> ModeSetRequest: + return ModeSetRequest.from_dict(s) -def session_plan_delete_result_from_dict(s: Any) -> SessionPlanDeleteResult: - return SessionPlanDeleteResult.from_dict(s) +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_plan_delete_result_to_dict(x: SessionPlanDeleteResult) -> Any: - return to_class(SessionPlanDeleteResult, x) +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_list_files_result_from_dict(s: Any) -> SessionWorkspaceListFilesResult: - return SessionWorkspaceListFilesResult.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 session_workspace_list_files_result_to_dict(x: SessionWorkspaceListFilesResult) -> Any: - return to_class(SessionWorkspaceListFilesResult, x) +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_read_file_result_from_dict(s: Any) -> SessionWorkspaceReadFileResult: - return SessionWorkspaceReadFileResult.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) -def session_workspace_read_file_result_to_dict(x: SessionWorkspaceReadFileResult) -> Any: - return to_class(SessionWorkspaceReadFileResult, x) +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_workspace_read_file_params_from_dict(s: Any) -> SessionWorkspaceReadFileParams: - return SessionWorkspaceReadFileParams.from_dict(s) +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_workspace_read_file_params_to_dict(x: SessionWorkspaceReadFileParams) -> Any: - return to_class(SessionWorkspaceReadFileParams, x) +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_workspace_create_file_result_from_dict(s: Any) -> SessionWorkspaceCreateFileResult: - return SessionWorkspaceCreateFileResult.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) -def session_workspace_create_file_result_to_dict(x: SessionWorkspaceCreateFileResult) -> Any: - return to_class(SessionWorkspaceCreateFileResult, x) +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_workspace_create_file_params_from_dict(s: Any) -> SessionWorkspaceCreateFileParams: - return SessionWorkspaceCreateFileParams.from_dict(s) +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_workspace_create_file_params_to_dict(x: SessionWorkspaceCreateFileParams) -> Any: - return to_class(SessionWorkspaceCreateFileParams, x) +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_fleet_start_result_from_dict(s: Any) -> SessionFleetStartResult: - return SessionFleetStartResult.from_dict(s) +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_fleet_start_result_to_dict(x: SessionFleetStartResult) -> Any: - return to_class(SessionFleetStartResult, x) +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_fleet_start_params_from_dict(s: Any) -> SessionFleetStartParams: - return SessionFleetStartParams.from_dict(s) +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_fleet_start_params_to_dict(x: SessionFleetStartParams) -> Any: - return to_class(SessionFleetStartParams, x) +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_list_result_from_dict(s: Any) -> SessionAgentListResult: - return SessionAgentListResult.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) -def session_agent_list_result_to_dict(x: SessionAgentListResult) -> Any: - return to_class(SessionAgentListResult, x) +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_get_current_result_from_dict(s: Any) -> SessionAgentGetCurrentResult: - return SessionAgentGetCurrentResult.from_dict(s) +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_get_current_result_to_dict(x: SessionAgentGetCurrentResult) -> Any: - return to_class(SessionAgentGetCurrentResult, x) +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_select_result_from_dict(s: Any) -> SessionAgentSelectResult: - return SessionAgentSelectResult.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 session_agent_select_result_to_dict(x: SessionAgentSelectResult) -> Any: - return to_class(SessionAgentSelectResult, x) +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_agent_select_params_from_dict(s: Any) -> SessionAgentSelectParams: - return SessionAgentSelectParams.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 session_agent_select_params_to_dict(x: SessionAgentSelectParams) -> Any: - return to_class(SessionAgentSelectParams, x) +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_agent_deselect_result_from_dict(s: Any) -> SessionAgentDeselectResult: - return SessionAgentDeselectResult.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 session_agent_deselect_result_to_dict(x: SessionAgentDeselectResult) -> Any: - return to_class(SessionAgentDeselectResult, x) +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_agent_reload_result_from_dict(s: Any) -> SessionAgentReloadResult: - return SessionAgentReloadResult.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 session_agent_reload_result_to_dict(x: SessionAgentReloadResult) -> Any: - return to_class(SessionAgentReloadResult, x) +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_list_result_from_dict(s: Any) -> SessionSkillsListResult: - return SessionSkillsListResult.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 session_skills_list_result_to_dict(x: SessionSkillsListResult) -> Any: - return to_class(SessionSkillsListResult, x) +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_enable_result_from_dict(s: Any) -> SessionSkillsEnableResult: - return SessionSkillsEnableResult.from_dict(s) +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_enable_result_to_dict(x: SessionSkillsEnableResult) -> Any: - return to_class(SessionSkillsEnableResult, x) +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_enable_params_from_dict(s: Any) -> SessionSkillsEnableParams: - return SessionSkillsEnableParams.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 session_skills_enable_params_to_dict(x: SessionSkillsEnableParams) -> Any: - return to_class(SessionSkillsEnableParams, x) +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_skills_disable_result_from_dict(s: Any) -> SessionSkillsDisableResult: - return SessionSkillsDisableResult.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 session_skills_disable_result_to_dict(x: SessionSkillsDisableResult) -> Any: - return to_class(SessionSkillsDisableResult, x) +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_skills_disable_params_from_dict(s: Any) -> SessionSkillsDisableParams: - return SessionSkillsDisableParams.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) -def session_skills_disable_params_to_dict(x: SessionSkillsDisableParams) -> Any: - return to_class(SessionSkillsDisableParams, x) +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_skills_reload_result_from_dict(s: Any) -> SessionSkillsReloadResult: - return SessionSkillsReloadResult.from_dict(s) +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_skills_reload_result_to_dict(x: SessionSkillsReloadResult) -> Any: - return to_class(SessionSkillsReloadResult, x) +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_list_result_from_dict(s: Any) -> SessionMCPListResult: - return SessionMCPListResult.from_dict(s) +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_list_result_to_dict(x: SessionMCPListResult) -> Any: - return to_class(SessionMCPListResult, x) +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_enable_result_from_dict(s: Any) -> SessionMCPEnableResult: - return SessionMCPEnableResult.from_dict(s) +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_enable_result_to_dict(x: SessionMCPEnableResult) -> Any: - return to_class(SessionMCPEnableResult, x) +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_enable_params_from_dict(s: Any) -> SessionMCPEnableParams: - return SessionMCPEnableParams.from_dict(s) +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_mcp_enable_params_to_dict(x: SessionMCPEnableParams) -> Any: - return to_class(SessionMCPEnableParams, x) +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_mcp_disable_result_from_dict(s: Any) -> SessionMCPDisableResult: - return SessionMCPDisableResult.from_dict(s) +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_mcp_disable_result_to_dict(x: SessionMCPDisableResult) -> Any: - return to_class(SessionMCPDisableResult, x) +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_mcp_disable_params_from_dict(s: Any) -> SessionMCPDisableParams: - return SessionMCPDisableParams.from_dict(s) +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_mcp_disable_params_to_dict(x: SessionMCPDisableParams) -> Any: - return to_class(SessionMCPDisableParams, x) +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_mcp_reload_result_from_dict(s: Any) -> SessionMCPReloadResult: - return SessionMCPReloadResult.from_dict(s) +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_mcp_reload_result_to_dict(x: SessionMCPReloadResult) -> Any: - return to_class(SessionMCPReloadResult, x) +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_plugins_list_result_from_dict(s: Any) -> SessionPluginsListResult: - return SessionPluginsListResult.from_dict(s) +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_plugins_list_result_to_dict(x: SessionPluginsListResult) -> Any: - return to_class(SessionPluginsListResult, x) +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_list_result_from_dict(s: Any) -> SessionExtensionsListResult: - return SessionExtensionsListResult.from_dict(s) +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_list_result_to_dict(x: SessionExtensionsListResult) -> Any: - return to_class(SessionExtensionsListResult, x) +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_enable_result_from_dict(s: Any) -> SessionExtensionsEnableResult: - return SessionExtensionsEnableResult.from_dict(s) - - -def session_extensions_enable_result_to_dict(x: SessionExtensionsEnableResult) -> Any: - return to_class(SessionExtensionsEnableResult, x) - - -def session_extensions_enable_params_from_dict(s: Any) -> SessionExtensionsEnableParams: - return SessionExtensionsEnableParams.from_dict(s) - - -def session_extensions_enable_params_to_dict(x: SessionExtensionsEnableParams) -> Any: - return to_class(SessionExtensionsEnableParams, x) - - -def session_extensions_disable_result_from_dict(s: Any) -> SessionExtensionsDisableResult: - return SessionExtensionsDisableResult.from_dict(s) - - -def session_extensions_disable_result_to_dict(x: SessionExtensionsDisableResult) -> Any: - return to_class(SessionExtensionsDisableResult, x) - - -def session_extensions_disable_params_from_dict(s: Any) -> SessionExtensionsDisableParams: - return SessionExtensionsDisableParams.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 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_params_to_dict(x: SessionFSReadFileParams) -> Any: - return to_class(SessionFSReadFileParams, x) - - -def session_fs_write_file_params_from_dict(s: Any) -> SessionFSWriteFileParams: - return SessionFSWriteFileParams.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_write_file_params_to_dict(x: SessionFSWriteFileParams) -> Any: - return to_class(SessionFSWriteFileParams, 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_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_request_to_dict(x: SessionFSStatRequest) -> Any: + return to_class(SessionFSStatRequest, x) -def session_fs_stat_params_to_dict(x: SessionFSStatParams) -> Any: - return to_class(SessionFSStatParams, x) - - -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_from_dict(s: Any) -> SessionFSMkdirRequest: + return SessionFSMkdirRequest.from_dict(s) +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_readdir_with_types_request_to_dict(x: SessionFSReaddirWithTypesRequest) -> Any: + return to_class(SessionFSReaddirWithTypesRequest, x) -def session_fs_rm_params_from_dict(s: Any) -> SessionFSRmParams: - return SessionFSRmParams.from_dict(s) +def session_fs_rm_request_from_dict(s: Any) -> SessionFSRmRequest: + return SessionFSRmRequest.from_dict(s) +def session_fs_rm_request_to_dict(x: SessionFSRmRequest) -> Any: + return to_class(SessionFSRmRequest, x) -def session_fs_rm_params_to_dict(x: SessionFSRmParams) -> Any: - return to_class(SessionFSRmParams, x) +def session_fs_rename_request_from_dict(s: Any) -> SessionFSRenameRequest: + return SessionFSRenameRequest.from_dict(s) - -def session_fs_rename_params_from_dict(s: Any) -> SessionFSRenameParams: - return SessionFSRenameParams.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: @@ -3846,37 +3791,41 @@ 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: 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))) + 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))) @@ -3886,7 +3835,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))) @@ -3902,7 +3851,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))) @@ -3912,13 +3861,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: @@ -3926,13 +3875,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) -> ModeGetResult: + return ModeGetResult.from_dict(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) -> ModeSetResult: 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 ModeSetResult.from_dict(await self._client.request("session.mode.set", params_dict, **_timeout_kwargs(timeout))) class PlanApi: @@ -3940,16 +3889,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: @@ -3957,18 +3906,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. @@ -3977,10 +3926,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. @@ -3989,22 +3938,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. @@ -4013,21 +3962,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. @@ -4036,21 +3985,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. @@ -4059,8 +4008,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. @@ -4069,21 +4018,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: @@ -4091,10 +4040,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: @@ -4102,10 +4051,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: @@ -4113,15 +4062,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: @@ -4129,10 +4078,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: @@ -4140,15 +4089,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. @@ -4157,13 +4106,23 @@ 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. +class UsageApi: + 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))) class SessionRpc: @@ -4187,33 +4146,34 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self.permissions = PermissionsApi(client, session_id) self.shell = ShellApi(client, session_id) 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 @@ -4226,70 +4186,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 dea0e79fd..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 Action(Enum): +class ElicitationCompletedAction(Enum): """The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) """ @@ -87,7 +87,7 @@ class Action(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,8 +863,15 @@ class Operation(Enum): UPDATE = "update" +class PermissionRequestMemoryAction(Enum): + """Whether this is a store or vote memory operation""" + + STORE = "store" + VOTE = "vote" + + @dataclass -class PermissionRequestCommand: +class PermissionRequestShellCommand: identifier: str """Command identifier (e.g., executable name)""" @@ -866,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 = {} @@ -879,7 +892,14 @@ def to_dict(self) -> dict: return result -class PermissionRequestKind(Enum): +class PermissionRequestMemoryDirection(Enum): + """Vote direction (vote only)""" + + DOWNVOTE = "downvote" + UPVOTE = "upvote" + + +class Kind(Enum): CUSTOM_TOOL = "custom-tool" HOOK = "hook" MCP = "mcp" @@ -891,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 = {} @@ -921,19 +941,19 @@ class PermissionRequest: URL access permission request - Memory storage permission request + Memory operation permission request Custom tool invocation permission request 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 @@ -954,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 @@ -999,14 +1019,23 @@ class PermissionRequest: url: str | None = None """URL to be fetched""" + action: PermissionRequestMemoryAction | None = None + """Whether this is a store or vote memory operation""" + citations: str | None = None - """Source references for the stored fact""" + """Source references for the stored fact (store only)""" + + direction: PermissionRequestMemoryDirection | None = None + """Vote direction (vote only)""" fact: str | None = None - """The fact or convention being stored""" + """The fact being stored or voted on""" + + reason: str | None = None + """Reason for the vote (vote only)""" subject: str | None = None - """Topic or subject of the memory being stored""" + """Topic or subject of the memory (store only)""" tool_description: str | None = None """Description of what the custom tool does""" @@ -1020,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")) @@ -1040,21 +1069,24 @@ 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([PermissionRequestMemoryAction, from_none], obj.get("action")) citations = from_union([from_str, from_none], obj.get("citations")) + 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")) tool_description = from_union([from_str, from_none], obj.get("toolDescription")) hook_message = from_union([from_str, from_none], obj.get("hookMessage")) tool_args = obj.get("toolArgs") - return PermissionRequest(kind, can_offer_session_approval, commands, full_command_text, has_write_file_redirection, intention, possible_paths, possible_urls, tool_call_id, warning, diff, file_name, new_file_contents, path, args, read_only, server_name, tool_name, tool_title, url, citations, fact, subject, tool_description, hook_message, tool_args) + return PermissionRequest(kind, can_offer_session_approval, commands, full_command_text, has_write_file_redirection, intention, possible_paths, possible_urls, tool_call_id, warning, diff, file_name, new_file_contents, path, args, read_only, server_name, tool_name, tool_title, url, action, citations, direction, fact, reason, subject, tool_description, hook_message, tool_args) 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: @@ -1064,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: @@ -1089,10 +1121,16 @@ def to_dict(self) -> dict: result["toolTitle"] = from_union([from_str, from_none], self.tool_title) 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(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(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: + result["reason"] = from_union([from_str, from_none], self.reason) if self.subject is not None: result["subject"] = from_union([from_str, from_none], self.subject) if self.tool_description is not None: @@ -1105,7 +1143,7 @@ def to_dict(self) -> dict: @dataclass -class QuotaSnapshot: +class AssistantUsageQuotaSnapshot: entitlement_requests: float """Total requests allowed by the entitlement""" @@ -1131,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")) @@ -1141,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 = {} @@ -1158,7 +1196,7 @@ def to_dict(self) -> dict: @dataclass -class RepositoryClass: +class HandoffRepository: """Repository context for the handed-off session""" name: str @@ -1171,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 = {} @@ -1192,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] @@ -1205,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 = {} @@ -1221,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" @@ -1229,7 +1267,7 @@ class Theme(Enum): @dataclass -class Icon: +class ToolExecutionCompleteContentResourceLinkIcon: """Icon image for a resource""" src: str @@ -1241,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 = {} @@ -1261,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 @@ -1284,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 = {} @@ -1304,7 +1342,7 @@ def to_dict(self) -> dict: return result -class ContentType(Enum): +class ToolExecutionCompleteContentType(Enum): AUDIO = "audio" IMAGE = "image" RESOURCE = "resource" @@ -1314,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 @@ -1330,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 @@ -1359,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 @@ -1374,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: @@ -1411,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: @@ -1421,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" @@ -1446,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 """ @@ -1454,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: @@ -1471,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 @@ -1500,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 @@ -1514,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: @@ -1541,7 +1579,7 @@ class ShutdownType(Enum): @dataclass -class Skill: +class SkillsLoadedSkill: description: str """Description of what the skill does""" @@ -1561,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")) @@ -1569,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 = {} @@ -1583,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" @@ -1591,7 +1629,7 @@ class SourceType(Enum): @dataclass -class StaticClientConfig: +class MCPOauthRequiredStaticClientConfig: """Static OAuth client configuration, if the server specifies one""" client_id: str @@ -1601,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 = {} @@ -1615,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. """ @@ -1624,7 +1662,7 @@ class ToolRequestType(Enum): @dataclass -class ToolRequest: +class AssistantMessageToolRequest: """A tool invocation request from the assistant""" name: str @@ -1645,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")) @@ -1659,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 = {} @@ -1675,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 = {} @@ -1846,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 @@ -1954,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 @@ -1974,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 @@ -2020,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 @@ -2043,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 @@ -2091,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 @@ -2106,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 @@ -2197,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 @@ -2287,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 @@ -2299,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 @@ -2327,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""" @@ -2454,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 @@ -2488,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: Action | None = None + action: ElicitationCompletedAction | None = None """The user action: "accept" (submitted form), "decline" (explicitly refused), or "cancel" (dismissed) """ @@ -2512,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 @@ -2532,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 @@ -2559,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 @@ -2571,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")) @@ -2610,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")) @@ -2628,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")) @@ -2645,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")) @@ -2660,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")) @@ -2678,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") @@ -2718,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")) @@ -2729,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([Action, 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")) @@ -2750,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: @@ -2816,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: @@ -2826,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: @@ -2852,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: @@ -2862,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: @@ -2886,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: @@ -2896,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: @@ -2916,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: @@ -2952,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: @@ -2960,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: @@ -2974,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: @@ -3032,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: @@ -3054,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(Action, 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: @@ -3066,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: @@ -3078,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: @@ -3096,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 b3f62789d..bea6f0fb3 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..072c8f4e2 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.mode == 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.mode == SessionMode.PLAN # Verify mode persisted after_plan = await session.rpc.mode.get() - assert after_plan.mode == Mode.PLAN + assert after_plan.mode == 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.mode == 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 9049cb38c..e7d81454f 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -12,13 +12,14 @@ 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, + isRpcMethod, REPO_ROOT, + writeGeneratedFile, type ApiSchema, type RpcMethod, } from "./utils.js"; @@ -199,12 +200,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[] = []; @@ -238,8 +239,7 @@ function extractEventVariants(schema: JSONSchema7): EventVariant[] { dataSchema, dataDescription: dataSchema?.description, }; - }) - .filter((v) => !EXCLUDED_EVENT_TYPES.has(v.typeName)); + }); } /** @@ -413,7 +413,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); @@ -423,11 +423,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}?`; } @@ -438,7 +438,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); @@ -446,12 +446,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); @@ -584,7 +584,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}`); @@ -608,12 +608,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 resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassName: string, propName: string, classes: string[]): string { @@ -627,7 +627,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) { @@ -638,17 +645,28 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam if (schema.type === "array" && schema.items) { const items = schema.items as JSONSchema7; if (items.type === "object" && items.properties) { - const itemClass = singularPascal(propName); + const itemClass = (items.title as string) ?? singularPascal(propName); if (!emittedRpcClasses.has(itemClass)) classes.push(emitRpcClass(itemClass, items, "public", classes)); 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 ? `List<${itemType}>` : `List<${itemType}>?`; } 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 ? `Dictionary` : `Dictionary?`; } @@ -785,7 +803,7 @@ function emitServerInstanceMethod( groupExperimental: boolean ): void { const methodName = toPascalCase(name); - const resultClassName = `${typeToClassName(method.rpcMethod)}Result`; + const resultClassName = resultTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } @@ -797,7 +815,7 @@ function emitServerInstanceMethod( let requestClassName: string | null = null; if (paramEntries.length > 0) { - requestClassName = `${typeToClassName(method.rpcMethod)}Request`; + requestClassName = paramsTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(requestClassName); } @@ -872,7 +890,7 @@ 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`; + const resultClassName = resultTypeName(method); if (method.stability === "experimental") { experimentalRpcTypes.add(resultClassName); } @@ -889,7 +907,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); } @@ -964,12 +982,12 @@ 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); + const resultClass = emitRpcClass(resultTypeName(method), method.result, "public", classes); if (resultClass) classes.push(resultClass); } 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); } } @@ -986,13 +1004,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);`); } @@ -1028,8 +1046,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) { @@ -1120,7 +1138,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..df7d01ff8 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,6 +912,7 @@ 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, ""); @@ -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..d7f83e0dc 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -10,12 +10,14 @@ 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, isRpcMethod, postProcessSchema, writeGeneratedFile, - isRpcMethod, isNodeFullyExperimental, type ApiSchema, type RpcMethod, @@ -118,6 +120,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 +199,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 +269,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 +284,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 +297,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 +337,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 +473,12 @@ 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 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 @@ -503,8 +574,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 +591,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); 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..62155b7d1 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,149 @@ 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; +} + +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