From 85a0b3b21804b5907c9d84195437e96787d4f362 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 22:05:52 +0000 Subject: [PATCH 1/6] Update @github/copilot to 1.0.51-1 - Updated nodejs and test harness dependencies - Re-ran code generators - Formatted generated code --- dotnet/src/Generated/Rpc.cs | 13919 ++++++++++++++----- dotnet/src/Generated/SessionEvents.cs | 263 +- go/rpc/zrpc.go | 5894 +++++++- go/rpc/zrpc_encoding.go | 1062 +- go/rpc/zsession_encoding.go | 203 - go/rpc/zsession_events.go | 325 +- go/zsession_events.go | 10 - nodejs/package-lock.json | 72 +- nodejs/package.json | 2 +- nodejs/samples/package-lock.json | 2 +- nodejs/src/generated/rpc.ts | 5417 +++++++- nodejs/src/generated/session-events.ts | 6 +- python/copilot/generated/rpc.py | 13754 ++++++++++++++---- python/copilot/generated/session_events.py | 506 +- rust/src/generated/api_types.rs | 8050 +++++++++-- rust/src/generated/rpc.rs | 3748 ++++- rust/src/generated/session_events.rs | 172 +- test/harness/package-lock.json | 72 +- test/harness/package.json | 2 +- 19 files changed, 42324 insertions(+), 11155 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 79649f1da..11eb343a1 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -18,7 +18,7 @@ namespace GitHub.Copilot.SDK.Rpc; -/// Server liveness response, including the echoed message, current timestamp, and protocol version. +/// Server liveness response, including the echoed message, current server timestamp, and protocol version. public sealed class PingResult { /// Echoed message (or default greeting). @@ -26,12 +26,13 @@ public sealed class PingResult public string Message { get; set; } = string.Empty; /// Server protocol version number. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("protocolVersion")] public long ProtocolVersion { get; set; } - /// Server timestamp in milliseconds. + /// ISO 8601 timestamp when the server handled the ping. [JsonPropertyName("timestamp")] - public long Timestamp { get; set; } + public DateTimeOffset Timestamp { get; set; } } /// Optional message to echo back to the caller. @@ -50,6 +51,7 @@ internal sealed class ConnectResult public bool Ok { get; set; } /// Server protocol version number. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("protocolVersion")] public long ProtocolVersion { get; set; } @@ -70,18 +72,22 @@ internal sealed class ConnectRequest public sealed class ModelBillingTokenPrices { /// Number of tokens per standard billing batch. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("batchSize")] public long? BatchSize { get; set; } /// Price per billing batch of cached tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cachePrice")] public long? CachePrice { get; set; } /// Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputPrice")] public long? InputPrice { get; set; } /// Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputPrice")] public long? OutputPrice { get; set; } } @@ -275,6 +281,7 @@ internal sealed class ToolsListRequest public sealed class AccountQuotaSnapshot { /// Number of requests included in the entitlement, or -1 for unlimited entitlements. + [Range((double)-1, (double)long.MaxValue)] [JsonPropertyName("entitlementRequests")] public long EntitlementRequests { get; set; } @@ -589,6 +596,7 @@ public sealed class ConnectedRemoteSessionMetadata public string? Name { get; set; } /// Pull request number associated with the session. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("pullRequestNumber")] public long? PullRequestNumber { get; set; } @@ -643,1094 +651,1575 @@ internal sealed class ConnectRemoteSessionParams public string SessionId { get; set; } = string.Empty; } -/// Identifies the target session. -internal sealed class SessionSuspendRequest +/// Schema for the `SessionContext` type. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionContext { - /// Target session identifier. + /// Active git branch. + [JsonPropertyName("branch")] + public string? Branch { get; set; } + + /// Most recent working directory for this session. + [JsonPropertyName("cwd")] + public string Cwd { get; set; } = string.Empty; + + /// Git repository root, if the cwd was inside a git repo. + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } + + /// Repository host type. + [JsonPropertyName("hostType")] + public SessionContextHostType? HostType { get; set; } + + /// Repository slug in `owner/name` form, when known. + [JsonPropertyName("repository")] + public string? Repository { get; set; } +} + +/// Schema for the `SessionMetadata` type. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionMetadata +{ + /// Schema for the `SessionContext` type. + [JsonPropertyName("context")] + public SessionContext? Context { get; set; } + + /// True for remote (GitHub) sessions; false for local. + [JsonPropertyName("isRemote")] + public bool IsRemote { get; set; } + + /// GitHub task ID, when this local session is bound to one. Only present for local sessions exported to remote control. + [JsonPropertyName("mcTaskId")] + public string? McTaskId { get; set; } + + /// Last-modified time of the session's persisted state, as ISO 8601. + [JsonPropertyName("modifiedTime")] + public string ModifiedTime { get; set; } = string.Empty; + + /// Optional human-friendly name set via /rename. + [JsonPropertyName("name")] + public string? Name { get; set; } + + /// Stable session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; + + /// Session creation time as an ISO 8601 timestamp. + [JsonPropertyName("startTime")] + public string StartTime { get; set; } = string.Empty; + + /// Short summary of the session, when one has been derived. + [JsonPropertyName("summary")] + public string? Summary { get; set; } } -/// Identifier of the session event that was emitted for the log message. -public sealed class LogResult +/// Persisted sessions matching the filter, ordered most-recently-modified first. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionList { - /// The unique identifier of the emitted session event. - [JsonPropertyName("eventId")] - public Guid EventId { get; set; } + /// Sessions ordered most-recently-modified first. + [JsonPropertyName("sessions")] + public IList Sessions { get => field ??= []; set; } } -/// Message text, optional severity level, persistence flag, and optional follow-up URL. -internal sealed class LogRequest +/// Optional filter applied to the returned sessions. +public sealed class SessionsListRequestFilter { - /// When true, the message is transient and not persisted to the session event log on disk. - [JsonPropertyName("ephemeral")] - public bool? Ephemeral { get; set; } - - /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". - [JsonPropertyName("level")] - public SessionLogLevel? Level { get; set; } + /// Match sessions whose context.branch equals this value. + [JsonPropertyName("branch")] + public string? Branch { get; set; } - /// Human-readable message. - [JsonPropertyName("message")] - public string Message { get; set; } = string.Empty; + /// Match sessions whose context.cwd equals this value. + [JsonPropertyName("cwd")] + public string? Cwd { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Match sessions whose context.gitRoot equals this value. + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } - /// Optional URL the user can open in their browser for more details. - [Url] - [StringSyntax(StringSyntaxAttribute.Uri)] - [JsonPropertyName("url")] - public string? Url { get; set; } + /// Match sessions whose context.repository equals this value. + [JsonPropertyName("repository")] + public string? Repository { get; set; } } -/// Authentication status and account metadata for the session. -public sealed class SessionAuthStatus +/// Optional metadata-load limit and context filter applied to the returned sessions. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsListRequest { - /// Authentication type. - [JsonPropertyName("authType")] - public AuthInfoType? AuthType { get; set; } + /// Optional filter applied to the returned sessions. + [JsonPropertyName("filter")] + public SessionsListRequestFilter? Filter { get; set; } - /// Copilot plan tier (e.g., individual_pro, business). - [JsonPropertyName("copilotPlan")] - public string? CopilotPlan { get; set; } + /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("metadataLimit")] + public long? MetadataLimit { get; set; } +} - /// Authentication host URL. - [Url] - [StringSyntax(StringSyntaxAttribute.Uri)] - [JsonPropertyName("host")] - public string? Host { get; set; } +/// ID of the local session bound to the given GitHub task, or omitted when none. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsFindByTaskIDResult +{ + /// Omitted when no local session is bound to that GitHub task. + [JsonPropertyName("sessionId")] + public string? SessionId { get; set; } +} - /// Whether the session has resolved authentication. - [JsonPropertyName("isAuthenticated")] - public bool IsAuthenticated { get; set; } +/// GitHub task ID to look up. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsFindByTaskIDRequest +{ + /// GitHub task ID to look up. + [JsonPropertyName("taskId")] + public string TaskId { get; set; } = string.Empty; +} - /// Authenticated login/username, if available. - [JsonPropertyName("login")] - public string? Login { get; set; } +/// Session ID matching the prefix, omitted when no unique match exists. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsFindByPrefixResult +{ + /// Omitted when no unique session matches the prefix (no match or ambiguous). + [JsonPropertyName("sessionId")] + public string? SessionId { get; set; } +} - /// Human-readable authentication status description. - [JsonPropertyName("statusMessage")] - public string? StatusMessage { get; set; } +/// UUID prefix to resolve to a unique session ID. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsFindByPrefixRequest +{ + /// UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when there is no match or the prefix matches multiple sessions. + [JsonPropertyName("prefix")] + public string Prefix { get; set; } = string.Empty; } -/// Identifies the target session. -internal sealed class SessionAuthGetStatusRequest +/// Most-relevant session ID for the supplied context, or omitted when no sessions exist. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsGetLastForContextResult { - /// Target session identifier. + /// Most-relevant session ID for the supplied context, or omitted when no sessions exist. [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + public string? SessionId { get; set; } } -/// The currently selected model for the session. -public sealed class CurrentModel +/// Optional working-directory context used to score session relevance. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsGetLastForContextRequest { - /// Currently active model identifier. - [JsonPropertyName("modelId")] - public string? ModelId { get; set; } + /// Optional working-directory context used to score session relevance. When omitted the most-recently-modified session wins. + [JsonPropertyName("context")] + public SessionContext? Context { get; set; } } -/// Identifies the target session. -internal sealed class SessionModelGetCurrentRequest +/// Absolute path to the session's events.jsonl file on disk. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsGetEventFilePathResult { - /// Target session identifier. + /// Absolute path to the session's events.jsonl file. + [JsonPropertyName("filePath")] + public string FilePath { get; set; } = string.Empty; +} + +/// Session ID whose event-log file path to compute. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsGetEventFilePathRequest +{ + /// Session ID whose event-log file path to compute. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// The model identifier active on the session after the switch. -public sealed class ModelSwitchToResult +/// Map of sessionId -> on-disk size in bytes for each session's workspace directory. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionSizes { - /// Currently active model identifier after the switch. - [JsonPropertyName("modelId")] - public string? ModelId { get; set; } + /// Map of sessionId -> on-disk size in bytes for the session's workspace directory. + [JsonPropertyName("sizes")] + public IDictionary Sizes { get => field ??= new Dictionary(); set; } } -/// Vision-specific limits. -public sealed class ModelCapabilitiesOverrideLimitsVision +/// Session IDs from the input set that are currently in use by another process. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsCheckInUseResult { - /// Maximum image size in bytes. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("max_prompt_image_size")] - public long? MaxPromptImageSize { get; set; } - - /// Maximum number of images per prompt. - [Range((double)1, (double)long.MaxValue)] - [JsonPropertyName("max_prompt_images")] - public long? MaxPromptImages { get; set; } + /// Session IDs from the input set that are currently held by another running process via an alive lock file. + [JsonPropertyName("inUse")] + public IList InUse { get => field ??= []; set; } +} - /// MIME types the model accepts. - [JsonPropertyName("supported_media_types")] - public IList? SupportedMediaTypes { get; set; } +/// Session IDs to test for live in-use locks. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsCheckInUseRequest +{ + /// Session IDs to test for live in-use locks. + [JsonPropertyName("sessionIds")] + public IList SessionIds { get => field ??= []; set; } } -/// Token limits for prompts, outputs, and context window. -public sealed class ModelCapabilitiesOverrideLimits +/// The session's persisted remote-steerable flag, or omitted when no value has been persisted. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsGetPersistedRemoteSteerableResult { - /// Maximum total context window size in tokens. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("max_context_window_tokens")] - public long? MaxContextWindowTokens { get; set; } + /// The session's persisted remote-steerable flag if recorded; omitted when no value has been persisted. + [JsonPropertyName("remoteSteerable")] + public bool? RemoteSteerable { get; set; } +} - /// Maximum number of output/completion tokens. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("max_output_tokens")] - public long? MaxOutputTokens { get; set; } +/// Session ID to look up the persisted remote-steerable flag for. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsGetPersistedRemoteSteerableRequest +{ + /// Session ID to look up the persisted remote-steerable flag for. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Maximum number of prompt/input tokens. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("max_prompt_tokens")] - public long? MaxPromptTokens { get; set; } +/// Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsCloseResult +{ +} - /// Vision-specific limits. - [JsonPropertyName("vision")] - public ModelCapabilitiesOverrideLimitsVision? Vision { get; set; } +/// Session ID to close. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsCloseRequest +{ + /// Session ID to close. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Feature flags indicating what the model supports. -public sealed class ModelCapabilitiesOverrideSupports +/// Map of sessionId -> bytes freed by removing the session's workspace directory. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionBulkDeleteResult { - /// Whether this model supports reasoning effort configuration. - [JsonPropertyName("reasoningEffort")] - public bool? ReasoningEffort { get; set; } + /// Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions whose deletion failed are omitted from this map (failures are logged on the server but not surfaced per-id; check the map for absent IDs to detect them). + [JsonPropertyName("freedBytes")] + public IDictionary FreedBytes { get => field ??= new Dictionary(); set; } +} - /// Whether this model supports vision/image input. - [JsonPropertyName("vision")] - public bool? Vision { get; set; } +/// Session IDs to close, deactivate, and delete from disk. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsBulkDeleteRequest +{ + /// Session IDs to close, deactivate, and delete from disk. + [JsonPropertyName("sessionIds")] + public IList SessionIds { get => field ??= []; set; } } -/// Override individual model capabilities resolved by the runtime. -public sealed class ModelCapabilitiesOverride +/// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionPruneResult { - /// Token limits for prompts, outputs, and context window. - [JsonPropertyName("limits")] - public ModelCapabilitiesOverrideLimits? Limits { get; set; } + /// Session IDs that would be deleted in dry-run mode (always empty otherwise). + [JsonPropertyName("candidates")] + public IList Candidates { get => field ??= []; set; } - /// Feature flags indicating what the model supports. - [JsonPropertyName("supports")] - public ModelCapabilitiesOverrideSupports? Supports { get; set; } + /// Session IDs that were deleted (always empty in dry-run mode). + [JsonPropertyName("deleted")] + public IList Deleted { get => field ??= []; set; } + + /// True when no deletions were actually performed. + [JsonPropertyName("dryRun")] + public bool DryRun { get; set; } + + /// Total bytes freed (actual when not dry-run, projected when dry-run). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("freedBytes")] + public long FreedBytes { get; set; } + + /// Session IDs that were skipped (e.g., named sessions). + [JsonPropertyName("skipped")] + public IList Skipped { get => field ??= []; set; } } -/// Target model identifier and optional reasoning effort, summary, and capability overrides. -internal sealed class ModelSwitchToRequest +/// Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true). +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsPruneOldRequest { - /// Override individual model capabilities resolved by the runtime. - [JsonPropertyName("modelCapabilities")] - public ModelCapabilitiesOverride? ModelCapabilities { get; set; } + /// When true, only report what would be deleted without performing any deletion. + [JsonPropertyName("dryRun")] + public bool? DryRun { get; set; } - /// Model identifier to switch to. - [JsonPropertyName("modelId")] - public string ModelId { get; set; } = string.Empty; + /// Session IDs that should never be considered for pruning. + [JsonPropertyName("excludeSessionIds")] + public IList? ExcludeSessionIds { get; set; } - /// Reasoning effort level to use for the model. "none" disables reasoning. - [JsonPropertyName("reasoningEffort")] - public string? ReasoningEffort { get; set; } + /// When true, named sessions (set via /rename) are also eligible for pruning. + [JsonPropertyName("includeNamed")] + public bool? IncludeNamed { get; set; } - /// Reasoning summary mode to request for supported model clients. - [JsonPropertyName("reasoningSummary")] - public ReasoningSummary? ReasoningSummary { get; set; } + /// Delete sessions whose modifiedTime is at least this many days old. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("olderThanDays")] + public long OlderThanDays { get; set; } +} - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; +/// Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsSaveResult +{ } -/// Identifies the target session. -internal sealed class SessionModeGetRequest +/// Session ID whose pending events should be flushed to disk. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsSaveRequest { - /// Target session identifier. + /// Session ID whose pending events should be flushed to disk. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Agent interaction mode to apply to the session. -internal sealed class ModeSetRequest +/// Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsReleaseLockResult { - /// The session mode the agent is operating in. - [JsonPropertyName("mode")] - public SessionMode Mode { get; set; } +} - /// Target session identifier. +/// Session ID whose in-use lock should be released. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsReleaseLockRequest +{ + /// Session ID whose in-use lock should be released. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// The session's friendly name, or null when not yet set. -public sealed class NameGetResult +/// The same metadata records, with summary and context fields backfilled where available. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionEnrichMetadataResult { - /// The session name (user-set or auto-generated), or null if not yet set. - [JsonPropertyName("name")] - public string? Name { get; set; } + /// Same records, with summary and context backfilled. + [JsonPropertyName("sessions")] + public IList Sessions { get => field ??= []; set; } } -/// Identifies the target session. -internal sealed class SessionNameGetRequest +/// Session metadata records to enrich with summary and context information. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsEnrichMetadataRequest { - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Session metadata records to enrich. Records that already have summary and context are returned unchanged. + [JsonPropertyName("sessions")] + public IList Sessions { get => field ??= []; set; } } -/// New friendly name to apply to the session. -internal sealed class NameSetRequest +/// Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsReloadPluginHooksResult { - /// New session name (1–100 characters, trimmed of leading/trailing whitespace). - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] - [MaxLength(100)] - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; +} - /// Target session identifier. +/// Active session ID and an optional flag for deferring repo-level hooks until folder trust. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsReloadPluginHooksRequest +{ + /// When true, skip repo-level hooks. Use before folder trust is confirmed; loadDeferredRepoHooks loads them post-trust. + [JsonPropertyName("deferRepoHooks")] + public bool? DeferRepoHooks { get; set; } + + /// Active session ID to reload hooks for. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Existence, contents, and resolved path of the session plan file. -public sealed class PlanReadResult +/// Queued repo-level startup prompts and the total hook command count after loading. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionLoadDeferredRepoHooksResult { - /// The content of the plan file, or null if it does not exist. - [JsonPropertyName("content")] - public string? Content { get; set; } - - /// Whether the plan file exists in the workspace. - [JsonPropertyName("exists")] - public bool Exists { get; set; } + /// Total hook command count (user + plugin + repo) loaded for the session by this call. Captured atomically with startupPrompts so callers don't need to read a separate counter. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("hookCount")] + public long HookCount { get; set; } - /// Absolute file path of the plan file, or null if workspace is not enabled. - [JsonPropertyName("path")] - public string? Path { get; set; } + /// Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo configs were pending, or when disableAllHooks is set. + [JsonPropertyName("startupPrompts")] + public IList StartupPrompts { get => field ??= []; set; } } -/// Identifies the target session. -internal sealed class SessionPlanReadRequest +/// Active session ID whose deferred repo-level hooks should be loaded. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsLoadDeferredRepoHooksRequest { - /// Target session identifier. + /// Active session ID whose deferred repo-level hooks should be loaded. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Replacement contents to write to the session plan file. -internal sealed class PlanUpdateRequest +/// Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionsSetAdditionalPluginsResult { - /// The new content for the plan file. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; +} - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; +/// Schema for the `InstalledPlugin` type. +[Experimental(Diagnostics.Experimental)] +public sealed class InstalledPlugin +{ + /// Path where the plugin is cached locally. + [JsonPropertyName("cache_path")] + public string? CachePath { get; set; } + + /// Whether the plugin is currently enabled. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } + + /// Installation timestamp. + [JsonPropertyName("installed_at")] + public string InstalledAt { get; set; } = string.Empty; + + /// Marketplace the plugin came from (empty string for direct repo installs). + [JsonPropertyName("marketplace")] + public string Marketplace { get; set; } = string.Empty; + + /// Plugin name. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// Source for direct repo installs (when marketplace is empty). + [JsonPropertyName("source")] + public object? Source { get; set; } + + /// Version installed (if available). + [JsonPropertyName("version")] + public string? Version { get; set; } +} + +/// Manager-wide additional plugins to register; replaces any previously-configured set. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionsSetAdditionalPluginsRequest +{ + /// Manager-wide additional plugins to register. Replaces any previously-configured set. Pass an empty array to clear. + [JsonPropertyName("plugins")] + public IList Plugins { get => field ??= []; set; } } /// Identifies the target session. -internal sealed class SessionPlanDeleteRequest +internal sealed class SessionSuspendRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// RPC data type for WorkspacesGetWorkspaceResultWorkspace operations. -public sealed class WorkspacesGetWorkspaceResultWorkspace +/// Result of sending a user message. +public sealed class SendResult { - /// Gets or sets the branch value. - [JsonPropertyName("branch")] - public string? Branch { get; set; } + /// Unique identifier assigned to the message. + [JsonPropertyName("messageId")] + public string MessageId { get; set; } = string.Empty; +} - /// Gets or sets the chronicle_sync_dismissed value. - [JsonPropertyName("chronicle_sync_dismissed")] - public bool? ChronicleSyncDismissed { get; set; } +/// A user message attachment — a file, directory, code selection, blob, or GitHub reference. +/// Polymorphic base type discriminated by type. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "type", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(SendAttachmentFile), "file")] +[JsonDerivedType(typeof(SendAttachmentDirectory), "directory")] +[JsonDerivedType(typeof(SendAttachmentSelection), "selection")] +[JsonDerivedType(typeof(SendAttachmentGithubReference), "github_reference")] +[JsonDerivedType(typeof(SendAttachmentBlob), "blob")] +public partial class SendAttachment +{ + /// The type discriminator. + [JsonPropertyName("type")] + public virtual string Type { get; set; } = string.Empty; +} - /// Gets or sets the created_at value. - [JsonPropertyName("created_at")] - public DateTimeOffset? CreatedAt { get; set; } - /// Gets or sets the cwd value. - [JsonPropertyName("cwd")] - public string? Cwd { get; set; } +/// Optional line range to scope the attachment to a specific section of the file. +public sealed class SendAttachmentFileLineRange +{ + /// End line number (1-based, inclusive). + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("end")] + public long End { get; set; } - /// Gets or sets the git_root value. - [JsonPropertyName("git_root")] - public string? GitRoot { get; set; } + /// Start line number (1-based). + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("start")] + public long Start { get; set; } +} - /// Gets or sets the host_type value. - [JsonPropertyName("host_type")] - public WorkspacesGetWorkspaceResultWorkspaceHostType? HostType { get; set; } +/// File attachment. +/// The file variant of . +public partial class SendAttachmentFile : SendAttachment +{ + /// + [JsonIgnore] + public override string Type => "file"; - /// Gets or sets the id value. - [JsonPropertyName("id")] - public Guid Id { get; set; } + /// User-facing display name for the attachment. + [JsonPropertyName("displayName")] + public required string DisplayName { get; set; } - /// Gets or sets the mc_last_event_id value. - [JsonPropertyName("mc_last_event_id")] - public string? McLastEventId { get; set; } + /// Optional line range to scope the attachment to a specific section of the file. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("lineRange")] + public SendAttachmentFileLineRange? LineRange { get; set; } - /// Gets or sets the mc_session_id value. - [JsonPropertyName("mc_session_id")] - public string? McSessionId { get; set; } + /// Absolute file path. + [JsonPropertyName("path")] + public required string Path { get; set; } +} - /// Gets or sets the mc_task_id value. - [JsonPropertyName("mc_task_id")] - public string? McTaskId { get; set; } +/// Directory attachment. +/// The directory variant of . +public partial class SendAttachmentDirectory : SendAttachment +{ + /// + [JsonIgnore] + public override string Type => "directory"; - /// Gets or sets the name value. - [JsonPropertyName("name")] - public string? Name { get; set; } + /// User-facing display name for the attachment. + [JsonPropertyName("displayName")] + public required string DisplayName { get; set; } - /// Gets or sets the remote_steerable value. - [JsonPropertyName("remote_steerable")] - public bool? RemoteSteerable { get; set; } + /// Absolute directory path. + [JsonPropertyName("path")] + public required string Path { get; set; } +} - /// Gets or sets the repository value. - [JsonPropertyName("repository")] - public string? Repository { get; set; } +/// End position of the selection. +public sealed class SendAttachmentSelectionDetailsEnd +{ + /// End character offset within the line (0-based). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("character")] + public long Character { get; set; } - /// Gets or sets the summary_count value. + /// End line number (0-based). [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("summary_count")] - public long? SummaryCount { get; set; } + [JsonPropertyName("line")] + public long Line { get; set; } +} - /// Gets or sets the updated_at value. - [JsonPropertyName("updated_at")] - public DateTimeOffset? UpdatedAt { get; set; } +/// Start position of the selection. +public sealed class SendAttachmentSelectionDetailsStart +{ + /// Start character offset within the line (0-based). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("character")] + public long Character { get; set; } - /// Gets or sets the user_named value. - [JsonPropertyName("user_named")] - public bool? UserNamed { get; set; } + /// Start line number (0-based). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("line")] + public long Line { get; set; } } -/// Current workspace metadata for the session, or null when not available. -public sealed class WorkspacesGetWorkspaceResult +/// Position range of the selection within the file. +public sealed class SendAttachmentSelectionDetails { - /// Current workspace metadata, or null if not available. - [JsonPropertyName("workspace")] - public WorkspacesGetWorkspaceResultWorkspace? Workspace { get; set; } + /// End position of the selection. + [JsonPropertyName("end")] + public SendAttachmentSelectionDetailsEnd End { get => field ??= new(); set; } + + /// Start position of the selection. + [JsonPropertyName("start")] + public SendAttachmentSelectionDetailsStart Start { get => field ??= new(); set; } } -/// Identifies the target session. -internal sealed class SessionWorkspacesGetWorkspaceRequest +/// Code selection attachment from an editor. +/// The selection variant of . +public partial class SendAttachmentSelection : SendAttachment { - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// + [JsonIgnore] + public override string Type => "selection"; + + /// User-facing display name for the selection. + [JsonPropertyName("displayName")] + public required string DisplayName { get; set; } + + /// Absolute path to the file containing the selection. + [JsonPropertyName("filePath")] + public required string FilePath { get; set; } + + /// Position range of the selection within the file. + [JsonPropertyName("selection")] + public required SendAttachmentSelectionDetails Selection { get; set; } + + /// The selected text content. + [JsonPropertyName("text")] + public required string Text { get; set; } } -/// Relative paths of files stored in the session workspace files directory. -public sealed class WorkspacesListFilesResult +/// GitHub issue, pull request, or discussion reference. +/// The github_reference variant of . +public partial class SendAttachmentGithubReference : SendAttachment { - /// Relative file paths in the workspace files directory. - [JsonPropertyName("files")] - public IList Files { get => field ??= []; set; } + /// + [JsonIgnore] + public override string Type => "github_reference"; + + /// Issue, pull request, or discussion number. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("number")] + public required long Number { get; set; } + + /// Type of GitHub reference. + [JsonPropertyName("referenceType")] + public required SendAttachmentGithubReferenceType ReferenceType { get; set; } + + /// Current state of the referenced item (e.g., open, closed, merged). + [JsonPropertyName("state")] + public required string State { get; set; } + + /// Title of the referenced item. + [JsonPropertyName("title")] + public required string Title { get; set; } + + /// URL to the referenced item on GitHub. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("url")] + public required string Url { get; set; } } -/// Identifies the target session. -internal sealed class SessionWorkspacesListFilesRequest +/// Blob attachment with inline base64-encoded data. +/// The blob variant of . +public partial class SendAttachmentBlob : SendAttachment +{ + /// + [JsonIgnore] + public override string Type => "blob"; + + /// Base64-encoded content. + [Base64String] + [JsonPropertyName("data")] + public required string Data { get; set; } + + /// User-facing display name for the attachment. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("displayName")] + public string? DisplayName { get; set; } + + /// MIME type of the inline data. + [JsonPropertyName("mimeType")] + public required string MimeType { get; set; } +} + +/// Parameters for sending a user message to the session. +internal sealed class SendRequest { + /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. + [JsonPropertyName("agentMode")] + public SendAgentMode? AgentMode { get; set; } + + /// Optional attachments (files, directories, selections, blobs, GitHub references) to include with the message. + [JsonPropertyName("attachments")] + public IList? Attachments { get; set; } + + /// If false, this message will not trigger a Premium Request Unit charge. User messages default to billable. + [JsonPropertyName("billable")] + public bool? Billable { get; set; } + + /// If provided, this is shown in the timeline instead of `prompt`. + [JsonPropertyName("displayPrompt")] + public string? DisplayPrompt { get; set; } + + /// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. + [JsonPropertyName("mode")] + public SendMode? Mode { get; set; } + + /// If true, adds the message to the front of the queue instead of the end. + [JsonPropertyName("prepend")] + public bool? Prepend { get; set; } + + /// The user message text. + [JsonPropertyName("prompt")] + public string Prompt { get; set; } = string.Empty; + + /// Custom HTTP headers to include in outbound model requests for this turn. Merged with session-level provider headers; per-turn headers augment and overwrite session-level headers with the same key. + [JsonPropertyName("requestHeaders")] + public IDictionary? RequestHeaders { get; set; } + + /// If set, the request will fail if the named tool is not available when this message is among the user messages at the start of the current exchange. + [JsonPropertyName("requiredTool")] + public string? RequiredTool { get; set; } + /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; + + /// Optional provenance tag copied to the resulting user.message event. Supported values are `system`, `command-*`, and `schedule-*`. + [JsonPropertyName("source")] + public object? Source { get; set; } + + /// W3C Trace Context traceparent header for distributed tracing of this agent turn. + [JsonPropertyName("traceparent")] + public string? Traceparent { get; set; } + + /// W3C Trace Context tracestate header for distributed tracing. + [JsonPropertyName("tracestate")] + public string? Tracestate { get; set; } + + /// If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. + [JsonPropertyName("wait")] + public bool? Wait { get; set; } } -/// Contents of the requested workspace file as a UTF-8 string. -public sealed class WorkspacesReadFileResult +/// Result of aborting the current turn. +public sealed class AbortResult { - /// File content as a UTF-8 string. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; + /// Error message if the abort failed. + [JsonPropertyName("error")] + public string? Error { get; set; } + + /// Whether the abort completed successfully. + [JsonPropertyName("success")] + public bool Success { get; set; } } -/// Relative path of the workspace file to read. -internal sealed class WorkspacesReadFileRequest +/// Parameters for aborting the current turn. +internal sealed class AbortRequest { - /// Relative path within the workspace files directory. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Finite reason code describing why the current turn was aborted. + [JsonPropertyName("reason")] + public AbortReason? Reason { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Relative path and UTF-8 content for the workspace file to create or overwrite. -internal sealed class WorkspacesCreateFileRequest +/// Parameters for shutting down the session. +internal sealed class ShutdownRequest { - /// File content to write as a UTF-8 string. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; - - /// Relative path within the workspace files directory. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. + [JsonPropertyName("reason")] + public string? Reason { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; + + /// Why the session is being shut down. Defaults to "routine" when omitted. + [JsonPropertyName("type")] + public ShutdownType? Type { get; set; } } -/// Schema for the `InstructionsSources` type. -public sealed class InstructionsSources +/// Identifier of the session event that was emitted for the log message. +public sealed class LogResult { - /// Glob pattern from frontmatter — when set, this instruction applies only to matching files. - [JsonPropertyName("applyTo")] - public string? ApplyTo { get; set; } + /// The unique identifier of the emitted session event. + [JsonPropertyName("eventId")] + public Guid EventId { get; set; } +} - /// Raw content of the instruction file. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; +/// Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. +internal sealed class LogRequest +{ + /// When true, the message is transient and not persisted to the session event log on disk. + [JsonPropertyName("ephemeral")] + public bool? Ephemeral { get; set; } - /// Short description (body after frontmatter) for use in instruction tables. - [JsonPropertyName("description")] - public string? Description { get; set; } - - /// Unique identifier for this source (used for toggling). - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". + [JsonPropertyName("level")] + public SessionLogLevel? Level { get; set; } - /// Human-readable label. - [JsonPropertyName("label")] - public string Label { get; set; } = string.Empty; + /// Human-readable message. + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; - /// Where this source lives — used for UI grouping. - [JsonPropertyName("location")] - public InstructionsSourcesLocation Location { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// File path relative to repo or absolute for home. - [JsonPropertyName("sourcePath")] - public string SourcePath { get; set; } = string.Empty; + /// Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. + [JsonPropertyName("tip")] + public string? Tip { get; set; } - /// Category of instruction source — used for merge logic. + /// Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". [JsonPropertyName("type")] - public InstructionsSourcesType Type { get; set; } + public string? Type { get; set; } + + /// Optional URL the user can open in their browser for more details. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("url")] + public string? Url { get; set; } } -/// Instruction sources loaded for the session, in merge order. -public sealed class InstructionsGetSourcesResult +/// Authentication status and account metadata for the session. +public sealed class SessionAuthStatus { - /// Instruction sources for the session. - [JsonPropertyName("sources")] - public IList Sources { get => field ??= []; set; } + /// Authentication type. + [JsonPropertyName("authType")] + public AuthInfoType? AuthType { get; set; } + + /// Copilot plan tier (e.g., individual_pro, business). + [JsonPropertyName("copilotPlan")] + public string? CopilotPlan { get; set; } + + /// Authentication host URL. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("host")] + public string? Host { get; set; } + + /// Whether the session has resolved authentication. + [JsonPropertyName("isAuthenticated")] + public bool IsAuthenticated { get; set; } + + /// Authenticated login/username, if available. + [JsonPropertyName("login")] + public string? Login { get; set; } + + /// Human-readable authentication status description. + [JsonPropertyName("statusMessage")] + public string? StatusMessage { get; set; } } /// Identifies the target session. -internal sealed class SessionInstructionsGetSourcesRequest +internal sealed class SessionAuthGetStatusRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether fleet mode was successfully activated. -[Experimental(Diagnostics.Experimental)] -public sealed class FleetStartResult +/// Indicates whether the credential update succeeded. +public sealed class SessionSetCredentialsResult { - /// Whether fleet mode was successfully activated. - [JsonPropertyName("started")] - public bool Started { get; set; } + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } } -/// Optional user prompt to combine with the fleet orchestration instructions. -[Experimental(Diagnostics.Experimental)] -internal sealed class FleetStartRequest +/// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. +/// Polymorphic base type discriminated by type. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "type", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(AuthInfoHmac), "hmac")] +[JsonDerivedType(typeof(AuthInfoEnv), "env")] +[JsonDerivedType(typeof(AuthInfoToken), "token")] +[JsonDerivedType(typeof(AuthInfoCopilotApiToken), "copilot-api-token")] +[JsonDerivedType(typeof(AuthInfoUser), "user")] +[JsonDerivedType(typeof(AuthInfoGhCli), "gh-cli")] +[JsonDerivedType(typeof(AuthInfoApiKey), "api-key")] +public partial class AuthInfo { - /// Optional user prompt to combine with fleet instructions. - [JsonPropertyName("prompt")] - public string? Prompt { get; set; } - - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// The type discriminator. + [JsonPropertyName("type")] + public virtual string Type { get; set; } = string.Empty; } -/// Schema for the `AgentInfo` type. -[Experimental(Diagnostics.Experimental)] -public sealed class AgentInfo + +/// Schema for the `CopilotUserResponseEndpoints` type. +public sealed class CopilotUserResponseEndpoints { - /// Description of the agent's purpose. - [JsonPropertyName("description")] - public string Description { get; set; } = string.Empty; + /// Gets or sets the api value. + [JsonPropertyName("api")] + public string? Api { get; set; } - /// Human-readable display name. - [JsonPropertyName("displayName")] - public string DisplayName { get; set; } = string.Empty; + /// Gets or sets the origin-tracker value. + [JsonPropertyName("origin-tracker")] + public string? OriginTracker { get; set; } - /// Unique identifier of the custom agent. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Gets or sets the proxy value. + [JsonPropertyName("proxy")] + public string? Proxy { get; set; } - /// Absolute local file path of the agent definition. Only set for file-based agents loaded from disk; remote agents do not have a path. - [JsonPropertyName("path")] - public string? Path { get; set; } + /// Gets or sets the telemetry value. + [JsonPropertyName("telemetry")] + public string? Telemetry { get; set; } } -/// Custom agents available to the session. -[Experimental(Diagnostics.Experimental)] -public sealed class AgentList +/// RPC data type for CopilotUserResponseOrganizationListItem operations. +public sealed class CopilotUserResponseOrganizationListItem { - /// Available custom agents. - [JsonPropertyName("agents")] - public IList Agents { get => field ??= []; set; } -} + /// Gets or sets the login value. + [JsonPropertyName("login")] + public string? Login { get; set; } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionAgentListRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Gets or sets the name value. + [JsonPropertyName("name")] + public string? Name { get; set; } } -/// The currently selected custom agent, or null when using the default agent. -[Experimental(Diagnostics.Experimental)] -public sealed class AgentGetCurrentResult +/// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. +public sealed class CopilotUserResponseQuotaSnapshotsChat { - /// Currently selected custom agent, or null if using the default agent. - [JsonPropertyName("agent")] - public AgentInfo? Agent { get; set; } -} + /// Gets or sets the entitlement value. + [JsonPropertyName("entitlement")] + public double? Entitlement { get; set; } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionAgentGetCurrentRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Gets or sets the has_quota value. + [JsonPropertyName("has_quota")] + public bool? HasQuota { get; set; } -/// The newly selected custom agent. -[Experimental(Diagnostics.Experimental)] -public sealed class AgentSelectResult -{ - /// The newly selected custom agent. - [JsonPropertyName("agent")] - public AgentInfo Agent { get => field ??= new(); set; } -} + /// Gets or sets the overage_count value. + [JsonPropertyName("overage_count")] + public double? OverageCount { get; set; } -/// Name of the custom agent to select for subsequent turns. -[Experimental(Diagnostics.Experimental)] -internal sealed class AgentSelectRequest -{ - /// Name of the custom agent to select. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Gets or sets the overage_permitted value. + [JsonPropertyName("overage_permitted")] + public bool? OveragePermitted { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Gets or sets the percent_remaining value. + [JsonPropertyName("percent_remaining")] + public double? PercentRemaining { get; set; } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionAgentDeselectRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Gets or sets the quota_id value. + [JsonPropertyName("quota_id")] + public string? QuotaId { get; set; } -/// Custom agents available to the session after reloading definitions from disk. -[Experimental(Diagnostics.Experimental)] -public sealed class AgentReloadResult -{ - /// Reloaded custom agents. - [JsonPropertyName("agents")] - public IList Agents { get => field ??= []; set; } -} + /// Gets or sets the quota_remaining value. + [JsonPropertyName("quota_remaining")] + public double? QuotaRemaining { get; set; } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionAgentReloadRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Gets or sets the quota_reset_at value. + [JsonPropertyName("quota_reset_at")] + public double? QuotaResetAt { get; set; } -/// Identifier assigned to the newly started background agent task. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksStartAgentResult -{ - /// Generated agent ID for the background task. - [JsonPropertyName("agentId")] - public string AgentId { get; set; } = string.Empty; + /// Gets or sets the remaining value. + [JsonPropertyName("remaining")] + public double? Remaining { get; set; } + + /// Gets or sets the timestamp_utc value. + [JsonPropertyName("timestamp_utc")] + public string? TimestampUtc { get; set; } + + /// Gets or sets the token_based_billing value. + [JsonPropertyName("token_based_billing")] + public bool? TokenBasedBilling { get; set; } + + /// Gets or sets the unlimited value. + [JsonPropertyName("unlimited")] + public bool? Unlimited { get; set; } } -/// Agent type, prompt, name, and optional description and model override for the new task. -[Experimental(Diagnostics.Experimental)] -internal sealed class TasksStartAgentRequest +/// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. +public sealed class CopilotUserResponseQuotaSnapshotsCompletions { - /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose'). - [JsonPropertyName("agentType")] - public string AgentType { get; set; } = string.Empty; + /// Gets or sets the entitlement value. + [JsonPropertyName("entitlement")] + public double? Entitlement { get; set; } - /// Short description of the task. - [JsonPropertyName("description")] - public string? Description { get; set; } + /// Gets or sets the has_quota value. + [JsonPropertyName("has_quota")] + public bool? HasQuota { get; set; } - /// Optional model override. - [JsonPropertyName("model")] - public string? Model { get; set; } + /// Gets or sets the overage_count value. + [JsonPropertyName("overage_count")] + public double? OverageCount { get; set; } - /// Short name for the agent, used to generate a human-readable ID. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Gets or sets the overage_permitted value. + [JsonPropertyName("overage_permitted")] + public bool? OveragePermitted { get; set; } - /// Task prompt for the agent. - [JsonPropertyName("prompt")] - public string Prompt { get; set; } = string.Empty; + /// Gets or sets the percent_remaining value. + [JsonPropertyName("percent_remaining")] + public double? PercentRemaining { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Gets or sets the quota_id value. + [JsonPropertyName("quota_id")] + public string? QuotaId { get; set; } + + /// Gets or sets the quota_remaining value. + [JsonPropertyName("quota_remaining")] + public double? QuotaRemaining { get; set; } + + /// Gets or sets the quota_reset_at value. + [JsonPropertyName("quota_reset_at")] + public double? QuotaResetAt { get; set; } + + /// Gets or sets the remaining value. + [JsonPropertyName("remaining")] + public double? Remaining { get; set; } + + /// Gets or sets the timestamp_utc value. + [JsonPropertyName("timestamp_utc")] + public string? TimestampUtc { get; set; } + + /// Gets or sets the token_based_billing value. + [JsonPropertyName("token_based_billing")] + public bool? TokenBasedBilling { get; set; } + + /// Gets or sets the unlimited value. + [JsonPropertyName("unlimited")] + public bool? Unlimited { get; set; } } -/// Schema for the `TaskInfo` type. -/// Polymorphic base type discriminated by type. -[Experimental(Diagnostics.Experimental)] -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "type", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(TaskInfoAgent), "agent")] -[JsonDerivedType(typeof(TaskInfoShell), "shell")] -public partial class TaskInfo +/// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. +public sealed class CopilotUserResponseQuotaSnapshotsPremiumInteractions { - /// The type discriminator. - [JsonPropertyName("type")] - public virtual string Type { get; set; } = string.Empty; -} + /// Gets or sets the entitlement value. + [JsonPropertyName("entitlement")] + public double? Entitlement { get; set; } + /// Gets or sets the has_quota value. + [JsonPropertyName("has_quota")] + public bool? HasQuota { get; set; } -/// Schema for the `TaskAgentInfo` type. -/// The agent variant of . -[Experimental(Diagnostics.Experimental)] -public partial class TaskInfoAgent : TaskInfo -{ - /// - [JsonIgnore] - public override string Type => "agent"; + /// Gets or sets the overage_count value. + [JsonPropertyName("overage_count")] + public double? OverageCount { get; set; } - /// ISO 8601 timestamp when the current active period began. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("activeStartedAt")] - public DateTimeOffset? ActiveStartedAt { get; set; } + /// Gets or sets the overage_permitted value. + [JsonPropertyName("overage_permitted")] + public bool? OveragePermitted { get; set; } - /// Accumulated active execution time in milliseconds. - [JsonConverter(typeof(MillisecondsTimeSpanConverter))] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("activeTimeMs")] - public TimeSpan? ActiveTime { get; set; } + /// Gets or sets the percent_remaining value. + [JsonPropertyName("percent_remaining")] + public double? PercentRemaining { get; set; } - /// Type of agent running this task. - [JsonPropertyName("agentType")] - public required string AgentType { get; set; } + /// Gets or sets the quota_id value. + [JsonPropertyName("quota_id")] + public string? QuotaId { get; set; } - /// Whether the task is currently in the original sync wait and can be moved to background mode. False once it is already backgrounded, idle, finished, or no longer has a promotable sync waiter. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("canPromoteToBackground")] - public bool? CanPromoteToBackground { get; set; } + /// Gets or sets the quota_remaining value. + [JsonPropertyName("quota_remaining")] + public double? QuotaRemaining { get; set; } - /// ISO 8601 timestamp when the task finished. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("completedAt")] - public DateTimeOffset? CompletedAt { get; set; } + /// Gets or sets the quota_reset_at value. + [JsonPropertyName("quota_reset_at")] + public double? QuotaResetAt { get; set; } - /// Short description of the task. - [JsonPropertyName("description")] - public required string Description { get; set; } + /// Gets or sets the remaining value. + [JsonPropertyName("remaining")] + public double? Remaining { get; set; } - /// Error message when the task failed. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("error")] - public string? Error { get; set; } + /// Gets or sets the timestamp_utc value. + [JsonPropertyName("timestamp_utc")] + public string? TimestampUtc { get; set; } - /// Whether task execution is synchronously awaited or managed in the background. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("executionMode")] - public TaskExecutionMode? ExecutionMode { get; set; } + /// Gets or sets the token_based_billing value. + [JsonPropertyName("token_based_billing")] + public bool? TokenBasedBilling { get; set; } - /// Unique task identifier. - [JsonPropertyName("id")] - public required string Id { get; set; } + /// Gets or sets the unlimited value. + [JsonPropertyName("unlimited")] + public bool? Unlimited { get; set; } +} - /// ISO 8601 timestamp when the agent entered idle state. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("idleSince")] - public DateTimeOffset? IdleSince { get; set; } +/// Schema for the `CopilotUserResponseQuotaSnapshots` type. +public sealed class CopilotUserResponseQuotaSnapshots +{ + /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. + [JsonPropertyName("chat")] + public CopilotUserResponseQuotaSnapshotsChat? Chat { get; set; } - /// Most recent response text from the agent. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("latestResponse")] - public string? LatestResponse { get; set; } + /// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. + [JsonPropertyName("completions")] + public CopilotUserResponseQuotaSnapshotsCompletions? Completions { get; set; } - /// Model used for the task when specified. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("model")] - public string? Model { get; set; } + /// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. + [JsonPropertyName("premium_interactions")] + public CopilotUserResponseQuotaSnapshotsPremiumInteractions? PremiumInteractions { get; set; } +} - /// Prompt passed to the agent. - [JsonPropertyName("prompt")] - public required string Prompt { get; set; } +/// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. +public sealed class CopilotUserResponse +{ + /// Gets or sets the access_type_sku value. + [JsonPropertyName("access_type_sku")] + public string? AccessTypeSku { get; set; } - /// Result text from the task when available. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("result")] - public string? Result { get; set; } + /// Gets or sets the analytics_tracking_id value. + [JsonPropertyName("analytics_tracking_id")] + public string? AnalyticsTrackingId { get; set; } - /// ISO 8601 timestamp when the task was started. - [JsonPropertyName("startedAt")] - public required DateTimeOffset StartedAt { get; set; } + /// Gets or sets the assigned_date value. + [JsonPropertyName("assigned_date")] + public string? AssignedDate { get; set; } - /// Current lifecycle status of the task. - [JsonPropertyName("status")] - public required TaskStatus Status { get; set; } + /// Gets or sets the can_signup_for_limited value. + [JsonPropertyName("can_signup_for_limited")] + public bool? CanSignupForLimited { get; set; } - /// Tool call ID associated with this agent task. - [JsonPropertyName("toolCallId")] - public required string ToolCallId { get; set; } + /// Gets or sets the chat_enabled value. + [JsonPropertyName("chat_enabled")] + public bool? ChatEnabled { get; set; } + + /// Gets or sets the cli_remote_control_enabled value. + [JsonPropertyName("cli_remote_control_enabled")] + public bool? CliRemoteControlEnabled { get; set; } + + /// Gets or sets the cloud_session_storage_enabled value. + [JsonPropertyName("cloud_session_storage_enabled")] + public bool? CloudSessionStorageEnabled { get; set; } + + /// Gets or sets the codex_agent_enabled value. + [JsonPropertyName("codex_agent_enabled")] + public bool? CodexAgentEnabled { get; set; } + + /// Gets or sets the copilot_plan value. + [JsonPropertyName("copilot_plan")] + public string? CopilotPlan { get; set; } + + /// Gets or sets the copilotignore_enabled value. + [JsonPropertyName("copilotignore_enabled")] + public bool? CopilotignoreEnabled { get; set; } + + /// Schema for the `CopilotUserResponseEndpoints` type. + [JsonPropertyName("endpoints")] + public CopilotUserResponseEndpoints? Endpoints { get; set; } + + /// Gets or sets the is_mcp_enabled value. + [JsonPropertyName("is_mcp_enabled")] + public bool? IsMcpEnabled { get; set; } + + /// Gets or sets the limited_user_quotas value. + [JsonPropertyName("limited_user_quotas")] + public IDictionary? LimitedUserQuotas { get; set; } + + /// Gets or sets the limited_user_reset_date value. + [JsonPropertyName("limited_user_reset_date")] + public string? LimitedUserResetDate { get; set; } + + /// Gets or sets the login value. + [JsonPropertyName("login")] + public string? Login { get; set; } + + /// Gets or sets the monthly_quotas value. + [JsonPropertyName("monthly_quotas")] + public IDictionary? MonthlyQuotas { get; set; } + + /// Gets or sets the organization_list value. + [JsonPropertyName("organization_list")] + public IList? OrganizationList { get; set; } + + /// Gets or sets the organization_login_list value. + [JsonPropertyName("organization_login_list")] + public IList? OrganizationLoginList { get; set; } + + /// Gets or sets the quota_reset_date value. + [JsonPropertyName("quota_reset_date")] + public string? QuotaResetDate { get; set; } + + /// Gets or sets the quota_reset_date_utc value. + [JsonPropertyName("quota_reset_date_utc")] + public string? QuotaResetDateUtc { get; set; } + + /// Schema for the `CopilotUserResponseQuotaSnapshots` type. + [JsonPropertyName("quota_snapshots")] + public CopilotUserResponseQuotaSnapshots? QuotaSnapshots { get; set; } + + /// Gets or sets the restricted_telemetry value. + [JsonPropertyName("restricted_telemetry")] + public bool? RestrictedTelemetry { get; set; } + + /// Gets or sets the token_based_billing value. + [JsonPropertyName("token_based_billing")] + public bool? TokenBasedBilling { get; set; } } -/// Schema for the `TaskShellInfo` type. -/// The shell variant of . -[Experimental(Diagnostics.Experimental)] -public partial class TaskInfoShell : TaskInfo +/// Schema for the `HMACAuthInfo` type. +/// The hmac variant of . +public partial class AuthInfoHmac : AuthInfo { /// [JsonIgnore] - public override string Type => "shell"; - - /// Whether the shell runs inside a managed PTY session or as an independent background process. - [JsonPropertyName("attachmentMode")] - public required TaskShellInfoAttachmentMode AttachmentMode { get; set; } + public override string Type => "hmac"; - /// Whether this shell task can be promoted to background mode. + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("canPromoteToBackground")] - public bool? CanPromoteToBackground { get; set; } + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } - /// Command being executed. - [JsonPropertyName("command")] - public required string Command { get; set; } + /// HMAC secret used to sign requests. + [JsonPropertyName("hmac")] + public required string Hmac { get; set; } - /// ISO 8601 timestamp when the task finished. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("completedAt")] - public DateTimeOffset? CompletedAt { get; set; } + /// Authentication host. HMAC auth always targets the public GitHub host. + [JsonPropertyName("host")] + public required string Host { get; set; } +} - /// Short description of the task. - [JsonPropertyName("description")] - public required string Description { get; set; } +/// Schema for the `EnvAuthInfo` type. +/// The env variant of . +public partial class AuthInfoEnv : AuthInfo +{ + /// + [JsonIgnore] + public override string Type => "env"; - /// Whether task execution is synchronously awaited or managed in the background. + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("executionMode")] - public TaskExecutionMode? ExecutionMode { get; set; } + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } - /// Unique task identifier. - [JsonPropertyName("id")] - public required string Id { get; set; } + /// Name of the environment variable the token was sourced from. + [JsonPropertyName("envVar")] + public required string EnvVar { get; set; } - /// Path to the detached shell log, when available. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("logPath")] - public string? LogPath { get; set; } + /// Authentication host (e.g. https://github.com or a GHES host). + [JsonPropertyName("host")] + public required string Host { get; set; } - /// Process ID when available. + /// User login associated with the token. Undefined for server-to-server tokens (those starting with `ghs_`). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("pid")] - public long? Pid { get; set; } - - /// ISO 8601 timestamp when the task was started. - [JsonPropertyName("startedAt")] - public required DateTimeOffset StartedAt { get; set; } + [JsonPropertyName("login")] + public string? Login { get; set; } - /// Current lifecycle status of the task. - [JsonPropertyName("status")] - public required TaskStatus Status { get; set; } + /// The token value itself. Treat as a secret. + [JsonPropertyName("token")] + public required string Token { get; set; } } -/// Background tasks currently tracked by the session. -[Experimental(Diagnostics.Experimental)] -public sealed class TaskList +/// Schema for the `TokenAuthInfo` type. +/// The token variant of . +public partial class AuthInfoToken : AuthInfo { - /// Currently tracked tasks. - [JsonPropertyName("tasks")] - public IList Tasks { get => field ??= []; set; } -} + /// + [JsonIgnore] + public override string Type => "token"; -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionTasksListRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } -/// Indicates whether the task was successfully promoted to background mode. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksPromoteToBackgroundResult -{ - /// Whether the task was successfully promoted to background mode. - [JsonPropertyName("promoted")] - public bool Promoted { get; set; } + /// Authentication host. + [JsonPropertyName("host")] + public required string Host { get; set; } + + /// The token value itself. Treat as a secret. + [JsonPropertyName("token")] + public required string Token { get; set; } } -/// Identifier of the task to promote to background mode. -[Experimental(Diagnostics.Experimental)] -internal sealed class TasksPromoteToBackgroundRequest +/// Schema for the `CopilotApiTokenAuthInfo` type. +/// The copilot-api-token variant of . +public partial class AuthInfoCopilotApiToken : AuthInfo { - /// Task identifier. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// + [JsonIgnore] + public override string Type => "copilot-api-token"; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } + + /// Authentication host (always the public GitHub host). + [JsonPropertyName("host")] + public required string Host { get; set; } } -/// Indicates whether the background task was successfully cancelled. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksCancelResult +/// Schema for the `UserAuthInfo` type. +/// The user variant of . +public partial class AuthInfoUser : AuthInfo { - /// Whether the task was successfully cancelled. - [JsonPropertyName("cancelled")] - public bool Cancelled { get; set; } + /// + [JsonIgnore] + public override string Type => "user"; + + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } + + /// Authentication host. + [JsonPropertyName("host")] + public required string Host { get; set; } + + /// OAuth user login. + [JsonPropertyName("login")] + public required string Login { get; set; } } -/// Identifier of the background task to cancel. -[Experimental(Diagnostics.Experimental)] -internal sealed class TasksCancelRequest +/// Schema for the `GhCliAuthInfo` type. +/// The gh-cli variant of . +public partial class AuthInfoGhCli : AuthInfo { - /// Task identifier. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// + [JsonIgnore] + public override string Type => "gh-cli"; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } + + /// Authentication host. + [JsonPropertyName("host")] + public required string Host { get; set; } + + /// User login as reported by `gh auth status`. + [JsonPropertyName("login")] + public required string Login { get; set; } + + /// The token returned by `gh auth token`. Treat as a secret. + [JsonPropertyName("token")] + public required string Token { get; set; } } -/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksRemoveResult +/// Schema for the `ApiKeyAuthInfo` type. +/// The api-key variant of . +public partial class AuthInfoApiKey : AuthInfo { - /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). - [JsonPropertyName("removed")] - public bool Removed { get; set; } + /// + [JsonIgnore] + public override string Type => "api-key"; + + /// The API key. Treat as a secret. + [JsonPropertyName("apiKey")] + public required string ApiKey { get; set; } + + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("copilotUser")] + public CopilotUserResponse? CopilotUser { get; set; } + + /// Authentication host. + [JsonPropertyName("host")] + public required string Host { get; set; } } -/// Identifier of the completed or cancelled task to remove from tracking. -[Experimental(Diagnostics.Experimental)] -internal sealed class TasksRemoveRequest +/// New auth credentials to install on the session. Omit to leave credentials unchanged. +internal sealed class SessionSetCredentialsParams { - /// Task identifier. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. + [JsonPropertyName("credentials")] + public AuthInfo? Credentials { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the message was delivered, with an error message when delivery failed. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksSendMessageResult +/// The currently selected model and reasoning effort for the session. +public sealed class CurrentModel { - /// Error message if delivery failed. - [JsonPropertyName("error")] - public string? Error { get; set; } + /// Currently active model identifier. + [JsonPropertyName("modelId")] + public string? ModelId { get; set; } - /// Whether the message was successfully delivered or steered. - [JsonPropertyName("sent")] - public bool Sent { get; set; } + /// Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. + [JsonPropertyName("reasoningEffort")] + public string? ReasoningEffort { get; set; } } -/// Identifier of the target agent task, message content, and optional sender agent ID. -[Experimental(Diagnostics.Experimental)] -internal sealed class TasksSendMessageRequest +/// Identifies the target session. +internal sealed class SessionModelGetCurrentRequest { - /// Agent ID of the sender, if sent on behalf of another agent. - [JsonPropertyName("fromAgentId")] - public string? FromAgentId { get; set; } - - /// Agent task identifier. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; - - /// Message content to send to the agent. - [JsonPropertyName("message")] - public string Message { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Schema for the `Skill` type. -[Experimental(Diagnostics.Experimental)] -public sealed class Skill +/// The model identifier active on the session after the switch. +public sealed class ModelSwitchToResult { - /// Description of what the skill does. - [JsonPropertyName("description")] - public string Description { get; set; } = string.Empty; + /// Currently active model identifier after the switch. + [JsonPropertyName("modelId")] + public string? ModelId { get; set; } +} - /// Whether the skill is currently enabled. - [JsonPropertyName("enabled")] - public bool Enabled { get; set; } +/// Vision-specific limits. +public sealed class ModelCapabilitiesOverrideLimitsVision +{ + /// Maximum image size in bytes. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("max_prompt_image_size")] + public long? MaxPromptImageSize { get; set; } - /// Unique identifier for the skill. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Maximum number of images per prompt. + [Range((double)1, (double)long.MaxValue)] + [JsonPropertyName("max_prompt_images")] + public long? MaxPromptImages { get; set; } - /// Absolute path to the skill file. - [JsonPropertyName("path")] - public string? Path { get; set; } + /// MIME types the model accepts. + [JsonPropertyName("supported_media_types")] + public IList? SupportedMediaTypes { get; set; } +} - /// Source location type (e.g., project, personal-copilot, plugin, builtin). - [JsonPropertyName("source")] - public SkillSource Source { get; set; } +/// Token limits for prompts, outputs, and context window. +public sealed class ModelCapabilitiesOverrideLimits +{ + /// Maximum total context window size in tokens. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("max_context_window_tokens")] + public long? MaxContextWindowTokens { get; set; } - /// Whether the skill can be invoked by the user as a slash command. - [JsonPropertyName("userInvocable")] - public bool UserInvocable { get; set; } + /// Maximum number of output/completion tokens. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("max_output_tokens")] + public long? MaxOutputTokens { get; set; } + + /// Maximum number of prompt/input tokens. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("max_prompt_tokens")] + public long? MaxPromptTokens { get; set; } + + /// Vision-specific limits. + [JsonPropertyName("vision")] + public ModelCapabilitiesOverrideLimitsVision? Vision { get; set; } } -/// Skills available to the session, with their enabled state. -[Experimental(Diagnostics.Experimental)] -public sealed class SkillList +/// Feature flags indicating what the model supports. +public sealed class ModelCapabilitiesOverrideSupports { - /// Available skills. - [JsonPropertyName("skills")] - public IList Skills { get => field ??= []; set; } + /// Whether this model supports reasoning effort configuration. + [JsonPropertyName("reasoningEffort")] + public bool? ReasoningEffort { get; set; } + + /// Whether this model supports vision/image input. + [JsonPropertyName("vision")] + public bool? Vision { get; set; } } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionSkillsListRequest +/// Override individual model capabilities resolved by the runtime. +public sealed class ModelCapabilitiesOverride +{ + /// Token limits for prompts, outputs, and context window. + [JsonPropertyName("limits")] + public ModelCapabilitiesOverrideLimits? Limits { get; set; } + + /// Feature flags indicating what the model supports. + [JsonPropertyName("supports")] + public ModelCapabilitiesOverrideSupports? Supports { get; set; } +} + +/// Target model identifier and optional reasoning effort, summary, and capability overrides. +internal sealed class ModelSwitchToRequest { + /// Override individual model capabilities resolved by the runtime. + [JsonPropertyName("modelCapabilities")] + public ModelCapabilitiesOverride? ModelCapabilities { get; set; } + + /// Model identifier to switch to. + [JsonPropertyName("modelId")] + public string ModelId { get; set; } = string.Empty; + + /// Reasoning effort level to use for the model. "none" disables reasoning. + [JsonPropertyName("reasoningEffort")] + public string? ReasoningEffort { get; set; } + + /// Reasoning summary mode to request for supported model clients. + [JsonPropertyName("reasoningSummary")] + public ReasoningSummary? ReasoningSummary { get; set; } + /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Name of the skill to enable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SkillsEnableRequest +/// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. +public sealed class ModelSetReasoningEffortResult { - /// Name of the skill to enable. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Reasoning effort level recorded on the session after the update. + [JsonPropertyName("reasoningEffort")] + public string ReasoningEffort { get; set; } = string.Empty; +} + +/// Reasoning effort level to apply to the currently selected model. +internal sealed class ModelSetReasoningEffortRequest +{ + /// Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. + [JsonPropertyName("reasoningEffort")] + public string ReasoningEffort { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Name of the skill to disable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SkillsDisableRequest +/// Identifies the target session. +internal sealed class SessionModeGetRequest { - /// Name of the skill to disable. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. -[Experimental(Diagnostics.Experimental)] -public sealed class SkillsLoadDiagnostics +/// Agent interaction mode to apply to the session. +internal sealed class ModeSetRequest { - /// Errors emitted while loading skills (e.g. skills that failed to load entirely). - [JsonPropertyName("errors")] - public IList Errors { get => field ??= []; set; } + /// The session mode the agent is operating in. + [JsonPropertyName("mode")] + public SessionMode Mode { get; set; } - /// Warnings emitted while loading skills (e.g. skills that loaded but had issues). - [JsonPropertyName("warnings")] - public IList Warnings { get => field ??= []; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// The session's friendly name, or null when not yet set. +public sealed class NameGetResult +{ + /// The session name (user-set or auto-generated), or null if not yet set. + [JsonPropertyName("name")] + public string? Name { get; set; } } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionSkillsReloadRequest +internal sealed class SessionNameGetRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Schema for the `McpServer` type. -[Experimental(Diagnostics.Experimental)] -public sealed class McpServer +/// New friendly name to apply to the session. +internal sealed class NameSetRequest { - /// Error message if the server failed to connect. - [JsonPropertyName("error")] - public string? Error { get; set; } - - /// Server name (config key). - [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] + /// New session name (1–100 characters, trimmed of leading/trailing whitespace). [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] [MinLength(1)] + [MaxLength(100)] [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; - /// Configuration source: user, workspace, plugin, or builtin. - [JsonPropertyName("source")] - public McpServerSource? Source { get; set; } - - /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. - [JsonPropertyName("status")] - public McpServerStatus Status { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// MCP servers configured for the session, with their connection status. -[Experimental(Diagnostics.Experimental)] -public sealed class McpServerList +/// Indicates whether the auto-generated summary was applied as the session's name. +public sealed class NameSetAutoResult { - /// Configured MCP servers. - [JsonPropertyName("servers")] - public IList Servers { get => field ??= []; set; } + /// Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. + [JsonPropertyName("applied")] + public bool Applied { get; set; } } -/// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionMcpListRequest +/// Auto-generated session summary to apply as the session's name when no user-set name exists. +internal sealed class NameSetAutoRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; + + /// Auto-generated session summary. Empty/whitespace-only values are ignored; values are trimmed before persisting. + [JsonPropertyName("summary")] + public string Summary { get; set; } = string.Empty; } -/// Name of the MCP server to enable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class McpEnableRequest +/// Existence, contents, and resolved path of the session plan file. +public sealed class PlanReadResult { - /// Name of the MCP server to enable. - [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] - [JsonPropertyName("serverName")] - public string ServerName { get; set; } = string.Empty; + /// The content of the plan file, or null if it does not exist. + [JsonPropertyName("content")] + public string? Content { get; set; } + + /// Whether the plan file exists in the workspace. + [JsonPropertyName("exists")] + public bool Exists { get; set; } + + /// Absolute file path of the plan file, or null if workspace is not enabled. + [JsonPropertyName("path")] + public string? Path { get; set; } +} +/// Identifies the target session. +internal sealed class SessionPlanReadRequest +{ /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Name of the MCP server to disable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class McpDisableRequest +/// Replacement contents to write to the session plan file. +internal sealed class PlanUpdateRequest { - /// Name of the MCP server to disable. - [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] - [JsonPropertyName("serverName")] - public string ServerName { get; set; } = string.Empty; + /// The new content for the plan file. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] @@ -1738,1286 +2227,1087 @@ internal sealed class McpDisableRequest } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionMcpReloadRequest +internal sealed class SessionPlanDeleteRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. -[Experimental(Diagnostics.Experimental)] -public sealed class McpOauthLoginResult -{ - /// URL the caller should open in a browser to complete OAuth. Omitted when cached tokens were still valid and no browser interaction was needed — the server is already reconnected in that case. When present, the runtime starts the callback listener before returning and continues the flow in the background; completion is signaled via session.mcp_server_status_changed. - [Url] - [StringSyntax(StringSyntaxAttribute.Uri)] - [JsonPropertyName("authorizationUrl")] - public string? AuthorizationUrl { get; set; } -} - -/// Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. -[Experimental(Diagnostics.Experimental)] -internal sealed class McpOauthLoginRequest +/// RPC data type for WorkspacesGetWorkspaceResultWorkspace operations. +public sealed class WorkspacesGetWorkspaceResultWorkspace { - /// Optional override for the body text shown on the OAuth loopback callback success page. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass surface-specific copy telling the user where to return. - [JsonPropertyName("callbackSuccessMessage")] - public string? CallbackSuccessMessage { get; set; } + /// Gets or sets the branch value. + [JsonPropertyName("branch")] + public string? Branch { get; set; } - /// Optional override for the OAuth client display name shown on the consent screen. Applies to newly registered dynamic clients only — existing registrations keep the name they were created with. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass their own surface-specific label so the consent screen matches the product the user sees. - [JsonPropertyName("clientName")] - public string? ClientName { get; set; } + /// Gets or sets the chronicle_sync_dismissed value. + [JsonPropertyName("chronicle_sync_dismissed")] + public bool? ChronicleSyncDismissed { get; set; } - /// When true, clears any cached OAuth token for the server and runs a full new authorization. Use when the user explicitly wants to switch accounts or believes their session is stuck. - [JsonPropertyName("forceReauth")] - public bool? ForceReauth { get; set; } + /// Gets or sets the created_at value. + [JsonPropertyName("created_at")] + public DateTimeOffset? CreatedAt { get; set; } - /// Name of the remote MCP server to authenticate. - [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] - [MinLength(1)] - [JsonPropertyName("serverName")] - public string ServerName { get; set; } = string.Empty; + /// Gets or sets the cwd value. + [JsonPropertyName("cwd")] + public string? Cwd { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Gets or sets the git_root value. + [JsonPropertyName("git_root")] + public string? GitRoot { get; set; } -/// Schema for the `Plugin` type. -[Experimental(Diagnostics.Experimental)] -public sealed class Plugin -{ - /// Whether the plugin is currently enabled. - [JsonPropertyName("enabled")] - public bool Enabled { get; set; } + /// Gets or sets the host_type value. + [JsonPropertyName("host_type")] + public WorkspacesGetWorkspaceResultWorkspaceHostType? HostType { get; set; } - /// Marketplace the plugin came from. - [JsonPropertyName("marketplace")] - public string Marketplace { get; set; } = string.Empty; + /// Gets or sets the id value. + [JsonPropertyName("id")] + public Guid Id { get; set; } - /// Plugin name. + /// Gets or sets the mc_last_event_id value. + [JsonPropertyName("mc_last_event_id")] + public string? McLastEventId { get; set; } + + /// Gets or sets the mc_session_id value. + [JsonPropertyName("mc_session_id")] + public string? McSessionId { get; set; } + + /// Gets or sets the mc_task_id value. + [JsonPropertyName("mc_task_id")] + public string? McTaskId { get; set; } + + /// Gets or sets the name value. [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + public string? Name { get; set; } - /// Installed version. - [JsonPropertyName("version")] - public string? Version { get; set; } + /// Gets or sets the remote_steerable value. + [JsonPropertyName("remote_steerable")] + public bool? RemoteSteerable { get; set; } + + /// Gets or sets the repository value. + [JsonPropertyName("repository")] + public string? Repository { get; set; } + + /// Gets or sets the summary_count value. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("summary_count")] + public long? SummaryCount { get; set; } + + /// Gets or sets the updated_at value. + [JsonPropertyName("updated_at")] + public DateTimeOffset? UpdatedAt { get; set; } + + /// Gets or sets the user_named value. + [JsonPropertyName("user_named")] + public bool? UserNamed { get; set; } } -/// Plugins installed for the session, with their enabled state and version metadata. -[Experimental(Diagnostics.Experimental)] -public sealed class PluginList +/// Current workspace metadata for the session, including its absolute filesystem path when available. +public sealed class WorkspacesGetWorkspaceResult { - /// Installed plugins. - [JsonPropertyName("plugins")] - public IList Plugins { get => field ??= []; set; } + /// Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). + [JsonPropertyName("path")] + public string? Path { get; set; } + + /// Current workspace metadata, or null if not available. + [JsonPropertyName("workspace")] + public WorkspacesGetWorkspaceResultWorkspace? Workspace { get; set; } } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionPluginsListRequest +internal sealed class SessionWorkspacesGetWorkspaceRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Schema for the `Extension` type. -[Experimental(Diagnostics.Experimental)] -public sealed class Extension -{ - /// Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper'). - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; - - /// Extension name (directory name). - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; - - /// Process ID if the extension is running. - [JsonPropertyName("pid")] - public long? Pid { get; set; } - - /// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/). - [JsonPropertyName("source")] - public ExtensionSource Source { get; set; } - - /// Current status: running, disabled, failed, or starting. - [JsonPropertyName("status")] - public ExtensionStatus Status { get; set; } -} - -/// Extensions discovered for the session, with their current status. -[Experimental(Diagnostics.Experimental)] -public sealed class ExtensionList +/// Relative paths of files stored in the session workspace files directory. +public sealed class WorkspacesListFilesResult { - /// Discovered extensions and their current status. - [JsonPropertyName("extensions")] - public IList Extensions { get => field ??= []; set; } + /// Relative file paths in the workspace files directory. + [JsonPropertyName("files")] + public IList Files { get => field ??= []; set; } } /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionExtensionsListRequest +internal sealed class SessionWorkspacesListFilesRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Source-qualified extension identifier to enable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class ExtensionsEnableRequest +/// Contents of the requested workspace file as a UTF-8 string. +public sealed class WorkspacesReadFileResult { - /// Source-qualified extension ID to enable. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// File content as a UTF-8 string. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; +} + +/// Relative path of the workspace file to read. +internal sealed class WorkspacesReadFileRequest +{ + /// Relative path within the workspace files directory. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Source-qualified extension identifier to disable for the session. -[Experimental(Diagnostics.Experimental)] -internal sealed class ExtensionsDisableRequest +/// Relative path and UTF-8 content for the workspace file to create or overwrite. +internal sealed class WorkspacesCreateFileRequest { - /// Source-qualified extension ID to disable. - [JsonPropertyName("id")] - public string Id { get; set; } = string.Empty; + /// File content to write as a UTF-8 string. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; + + /// Relative path within the workspace files directory. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } +/// Schema for the `WorkspacesCheckpoints` type. +public sealed class WorkspacesCheckpoints +{ + /// Filename of the checkpoint within the workspace checkpoints directory. + [JsonPropertyName("filename")] + public string Filename { get; set; } = string.Empty; + + /// Checkpoint number assigned by the workspace manager. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("number")] + public long Number { get; set; } + + /// Human-readable checkpoint title. + [JsonPropertyName("title")] + public string Title { get; set; } = string.Empty; +} + +/// Workspace checkpoints in chronological order; empty when the workspace is not enabled. +public sealed class WorkspacesListCheckpointsResult +{ + /// Workspace checkpoints in chronological order. Empty when workspace is not enabled. + [JsonPropertyName("checkpoints")] + public IList Checkpoints { get => field ??= []; set; } +} + /// Identifies the target session. -[Experimental(Diagnostics.Experimental)] -internal sealed class SessionExtensionsReloadRequest +internal sealed class SessionWorkspacesListCheckpointsRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the external tool call result was handled successfully. -public sealed class HandlePendingToolCallResult +/// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. +public sealed class WorkspacesReadCheckpointResult { - /// Whether the tool call result was handled successfully. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. + [JsonPropertyName("content")] + public string? Content { get; set; } } -/// Pending external tool call request ID, with the tool result or an error describing why it failed. -internal sealed class HandlePendingToolCallRequest +/// Checkpoint number to read. +internal sealed class WorkspacesReadCheckpointRequest { - /// Error message if the tool call failed. - [JsonPropertyName("error")] - public string? Error { get; set; } - - /// Request ID of the pending tool call. - [JsonPropertyName("requestId")] - public string RequestId { get; set; } = string.Empty; - - /// Tool call result (string or expanded result object). - [JsonPropertyName("result")] - public object? Result { get; set; } + /// Checkpoint number to read. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("number")] + public long Number { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Optional unstructured input hint. -public sealed class SlashCommandInput +/// RPC data type for WorkspacesSaveLargePasteResultSaved operations. +public sealed class WorkspacesSaveLargePasteResultSaved { - /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). - [JsonPropertyName("completion")] - public SlashCommandInputCompletion? Completion { get; set; } - - /// Hint to display when command input has not been provided. - [JsonPropertyName("hint")] - public string Hint { get; set; } = string.Empty; + /// Filename within the workspace files directory. + [JsonPropertyName("filename")] + public string Filename { get; set; } = string.Empty; - /// When true, clients should pass the full text after the command name as a single argument rather than splitting on whitespace. - [JsonPropertyName("preserveMultilineInput")] - public bool? PreserveMultilineInput { get; set; } + /// Absolute filesystem path to the saved paste file. + [JsonPropertyName("filePath")] + public string FilePath { get; set; } = string.Empty; - /// When true, the command requires non-empty input; clients should render the input hint as required. - [JsonPropertyName("required")] - public bool? Required { get; set; } + /// Size of the saved file in bytes. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("sizeBytes")] + public long SizeBytes { get; set; } } -/// Schema for the `SlashCommandInfo` type. -public sealed class SlashCommandInfo +/// Descriptor for the saved paste file, or null when the workspace is unavailable. +public sealed class WorkspacesSaveLargePasteResult { - /// Canonical aliases without leading slashes. - [JsonPropertyName("aliases")] - public IList? Aliases { get; set; } + /// Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions). + [JsonPropertyName("saved")] + public WorkspacesSaveLargePasteResultSaved? Saved { get; set; } +} - /// Whether the command may run while an agent turn is active. - [JsonPropertyName("allowDuringAgentExecution")] - public bool AllowDuringAgentExecution { get; set; } +/// Pasted content to save as a UTF-8 file in the session workspace. +internal sealed class WorkspacesSaveLargePasteRequest +{ + /// Pasted content to save as a UTF-8 file. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; - /// Human-readable command description. - [JsonPropertyName("description")] - public string Description { get; set; } = string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Whether the command is experimental. - [JsonPropertyName("experimental")] - public bool? Experimental { get; set; } +/// Schema for the `InstructionsSources` type. +public sealed class InstructionsSources +{ + /// Glob pattern(s) from frontmatter — when set, this instruction applies only to matching files. + [JsonPropertyName("applyTo")] + public IList? ApplyTo { get; set; } - /// Optional unstructured input hint. - [JsonPropertyName("input")] - public SlashCommandInput? Input { get; set; } + /// Raw content of the instruction file. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; - /// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. - [JsonPropertyName("kind")] - public SlashCommandKind Kind { get; set; } + /// When true, this source starts disabled and must be toggled on by the user. + [JsonPropertyName("defaultDisabled")] + public bool? DefaultDisabled { get; set; } - /// Canonical command name without a leading slash. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; -} + /// Short description (body after frontmatter) for use in instruction tables. + [JsonPropertyName("description")] + public string? Description { get; set; } -/// Slash commands available in the session, after applying any include/exclude filters. -public sealed class CommandList -{ - /// Commands available in this session. - [JsonPropertyName("commands")] - public IList Commands { get => field ??= []; set; } -} + /// Unique identifier for this source (used for toggling). + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; -/// Optional filters controlling which command sources to include in the listing. -public sealed class CommandsListRequest -{ - /// Include runtime built-in commands. - [JsonPropertyName("includeBuiltins")] - public bool? IncludeBuiltins { get; set; } + /// Human-readable label. + [JsonPropertyName("label")] + public string Label { get; set; } = string.Empty; - /// Include commands registered by protocol clients, including SDK clients and extensions. - [JsonPropertyName("includeClientCommands")] - public bool? IncludeClientCommands { get; set; } + /// Where this source lives — used for UI grouping. + [JsonPropertyName("location")] + public InstructionsSourcesLocation Location { get; set; } - /// Include enabled user-invocable skills and commands. - [JsonPropertyName("includeSkills")] - public bool? IncludeSkills { get; set; } + /// File path relative to repo or absolute for home. + [JsonPropertyName("sourcePath")] + public string SourcePath { get; set; } = string.Empty; + + /// Category of instruction source — used for merge logic. + [JsonPropertyName("type")] + public InstructionsSourcesType Type { get; set; } } -/// Optional filters controlling which command sources to include in the listing. -internal sealed class CommandsListRequestWithSession +/// Instruction sources loaded for the session, in merge order. +public sealed class InstructionsGetSourcesResult { - /// Include runtime built-in commands. - [JsonPropertyName("includeBuiltins")] - public bool? IncludeBuiltins { get; set; } - - /// Include commands registered by protocol clients, including SDK clients and extensions. - [JsonPropertyName("includeClientCommands")] - public bool? IncludeClientCommands { get; set; } - - /// Include enabled user-invocable skills and commands. - [JsonPropertyName("includeSkills")] - public bool? IncludeSkills { get; set; } + /// Instruction sources for the session. + [JsonPropertyName("sources")] + public IList Sources { get => field ??= []; set; } +} +/// Identifies the target session. +internal sealed class SessionInstructionsGetSourcesRequest +{ /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Result of invoking the slash command (text output, prompt to send to the agent, or completion). -/// Polymorphic base type discriminated by kind. -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "kind", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(SlashCommandInvocationResultText), "text")] -[JsonDerivedType(typeof(SlashCommandInvocationResultAgentPrompt), "agent-prompt")] -[JsonDerivedType(typeof(SlashCommandInvocationResultCompleted), "completed")] -public partial class SlashCommandInvocationResult +/// Indicates whether fleet mode was successfully activated. +[Experimental(Diagnostics.Experimental)] +public sealed class FleetStartResult { - /// The type discriminator. - [JsonPropertyName("kind")] - public virtual string Kind { get; set; } = string.Empty; + /// Whether fleet mode was successfully activated. + [JsonPropertyName("started")] + public bool Started { get; set; } } - -/// Schema for the `SlashCommandTextResult` type. -/// The text variant of . -public partial class SlashCommandInvocationResultText : SlashCommandInvocationResult +/// Optional user prompt to combine with the fleet orchestration instructions. +[Experimental(Diagnostics.Experimental)] +internal sealed class FleetStartRequest { - /// - [JsonIgnore] - public override string Kind => "text"; + /// Optional user prompt to combine with fleet instructions. + [JsonPropertyName("prompt")] + public string? Prompt { get; set; } - /// Whether text contains Markdown. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("markdown")] - public bool? Markdown { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Whether ANSI sequences should be preserved. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("preserveAnsi")] - public bool? PreserveAnsi { get; set; } +/// Schema for the `AgentInfo` type. +[Experimental(Diagnostics.Experimental)] +public sealed class AgentInfo +{ + /// Description of the agent's purpose. + [JsonPropertyName("description")] + public string Description { get; set; } = string.Empty; - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("runtimeSettingsChanged")] - public bool? RuntimeSettingsChanged { get; set; } + /// Human-readable display name. + [JsonPropertyName("displayName")] + public string DisplayName { get; set; } = string.Empty; - /// Text output for the client to render. - [JsonPropertyName("text")] - public required string Text { get; set; } -} + /// Stable identifier for selection. For most agents this is the same as `name`; for plugin/builtin agents it may differ. Always populated; defaults to `name` when no distinct id was assigned. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; -/// Schema for the `SlashCommandAgentPromptResult` type. -/// The agent-prompt variant of . -public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvocationResult -{ - /// - [JsonIgnore] - public override string Kind => "agent-prompt"; + /// MCP server configurations attached to this agent, keyed by server name. Server config shape mirrors the MCP `mcpServers` schema. + [JsonPropertyName("mcpServers")] + public IDictionary? McpServers { get; set; } - /// Prompt text to display to the user. - [JsonPropertyName("displayPrompt")] - public required string DisplayPrompt { get; set; } + /// Preferred model id for this agent. When omitted, inherits the outer agent's model. + [JsonPropertyName("model")] + public string? Model { get; set; } - /// Optional target session mode for the agent prompt. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("mode")] - public SessionMode? Mode { get; set; } + /// Unique identifier of the custom agent. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Prompt to submit to the agent. - [JsonPropertyName("prompt")] - public required string Prompt { get; set; } + /// Absolute local file path of the agent definition. Only set for file-based agents loaded from disk; remote agents do not have a path. + [JsonPropertyName("path")] + public string? Path { get; set; } - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("runtimeSettingsChanged")] - public bool? RuntimeSettingsChanged { get; set; } -} + /// Skill names preloaded into this agent's context. Omitted means none. + [JsonPropertyName("skills")] + public IList? Skills { get; set; } -/// Schema for the `SlashCommandCompletedResult` type. -/// The completed variant of . -public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocationResult -{ - /// - [JsonIgnore] - public override string Kind => "completed"; + /// Where the agent definition was loaded from. + [JsonPropertyName("source")] + public AgentInfoSource? Source { get; set; } - /// Optional user-facing message describing the completed command. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("message")] - public string? Message { get; set; } + /// Allowed tool names for this agent. Empty array means none; omitted means inherit defaults. + [JsonPropertyName("tools")] + public IList? Tools { get; set; } - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("runtimeSettingsChanged")] - public bool? RuntimeSettingsChanged { get; set; } + /// Whether the agent can be selected directly by the user. Agents marked `false` are subagent-only. + [JsonPropertyName("userInvocable")] + public bool? UserInvocable { get; set; } } -/// Slash command name and optional raw input string to invoke. -internal sealed class CommandsInvokeRequest +/// Custom agents available to the session. +[Experimental(Diagnostics.Experimental)] +public sealed class AgentList { - /// Raw input after the command name. - [JsonPropertyName("input")] - public string? Input { get; set; } - - /// Command name. Leading slashes are stripped and the name is matched case-insensitively. - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; + /// Available custom agents. + [JsonPropertyName("agents")] + public IList Agents { get => field ??= []; set; } +} +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionAgentListRequest +{ /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the pending client-handled command was completed successfully. -public sealed class CommandsHandlePendingCommandResult +/// The currently selected custom agent, or null when using the default agent. +[Experimental(Diagnostics.Experimental)] +public sealed class AgentGetCurrentResult { - /// Whether the command was handled successfully. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Currently selected custom agent, or null if using the default agent. + [JsonPropertyName("agent")] + public AgentInfo? Agent { get; set; } } -/// Pending command request ID and an optional error if the client handler failed. -internal sealed class CommandsHandlePendingCommandRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionAgentGetCurrentRequest { - /// Error message if the command handler failed. - [JsonPropertyName("error")] - public string? Error { get; set; } - - /// Request ID from the command invocation event. - [JsonPropertyName("requestId")] - public string RequestId { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the queued-command response was accepted by the session. -public sealed class CommandsRespondToQueuedCommandResult +/// The newly selected custom agent. +[Experimental(Diagnostics.Experimental)] +public sealed class AgentSelectResult { - /// Whether the response was accepted (false if the requestId was not found or already resolved). - [JsonPropertyName("success")] - public bool Success { get; set; } + /// The newly selected custom agent. + [JsonPropertyName("agent")] + public AgentInfo Agent { get => field ??= new(); set; } } -/// Result of the queued command execution. -/// Data type discriminated by handled. -public partial class QueuedCommandResult +/// Name of the custom agent to select for subsequent turns. +[Experimental(Diagnostics.Experimental)] +internal sealed class AgentSelectRequest { - /// The boolean discriminator. - [JsonPropertyName("handled")] - public bool Handled { get; set; } + /// Name of the custom agent to select. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// If true, stop processing remaining queued items. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("stopProcessingQueue")] - public bool? StopProcessingQueue { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Queued command request ID and the result indicating whether the client handled it. -internal sealed class CommandsRespondToQueuedCommandRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionAgentDeselectRequest { - /// Request ID from the queued command event. - [JsonPropertyName("requestId")] - public string RequestId { get; set; } = string.Empty; - - /// Result of the queued command execution. - [JsonPropertyName("result")] - public QueuedCommandResult Result { get => field ??= new(); set; } - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// The elicitation response (accept with form values, decline, or cancel). -public sealed class UIElicitationResponse +/// Custom agents available to the session after reloading definitions from disk. +[Experimental(Diagnostics.Experimental)] +public sealed class AgentReloadResult { - /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). - [JsonPropertyName("action")] - public UIElicitationResponseAction Action { get; set; } - - /// The form values submitted by the user (present when action is 'accept'). - [JsonPropertyName("content")] - public IDictionary? Content { get; set; } -} - -/// JSON Schema describing the form fields to present to the user. -public sealed class UIElicitationSchema -{ - /// Form field definitions, keyed by field name. - [JsonPropertyName("properties")] - public IDictionary Properties { get => field ??= new Dictionary(); set; } - - /// List of required field names. - [JsonPropertyName("required")] - public IList? Required { get; set; } - - /// Schema type indicator (always 'object'). - [JsonPropertyName("type")] - public string Type { get; set; } = string.Empty; + /// Reloaded custom agents. + [JsonPropertyName("agents")] + public IList Agents { get => field ??= []; set; } } -/// Prompt message and JSON schema describing the form fields to elicit from the user. -internal sealed class UIElicitationRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionAgentReloadRequest { - /// Message describing what information is needed from the user. - [JsonPropertyName("message")] - public string Message { get; set; } = string.Empty; - - /// JSON Schema describing the form fields to present to the user. - [JsonPropertyName("requestedSchema")] - public UIElicitationSchema RequestedSchema { get => field ??= new(); set; } - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. -public sealed class UIElicitationResult +/// Identifier assigned to the newly started background agent task. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksStartAgentResult { - /// Whether the response was accepted. False if the request was already resolved by another client. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Generated agent ID for the background task. + [JsonPropertyName("agentId")] + public string AgentId { get; set; } = string.Empty; } -/// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). -internal sealed class UIHandlePendingElicitationRequest +/// Agent type, prompt, name, and optional description and model override for the new task. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksStartAgentRequest { - /// The unique request ID from the elicitation.requested event. - [JsonPropertyName("requestId")] - public string RequestId { get; set; } = string.Empty; + /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose'). + [JsonPropertyName("agentType")] + public string AgentType { get; set; } = string.Empty; - /// The elicitation response (accept with form values, decline, or cancel). - [JsonPropertyName("result")] - public UIElicitationResponse Result { get => field ??= new(); set; } + /// Short description of the task. + [JsonPropertyName("description")] + public string? Description { get; set; } + + /// Optional model override. + [JsonPropertyName("model")] + public string? Model { get; set; } + + /// Short name for the agent, used to generate a human-readable ID. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// Task prompt for the agent. + [JsonPropertyName("prompt")] + public string Prompt { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the permission decision was applied; false when the request was already resolved. -public sealed class PermissionRequestResult -{ - /// Whether the permission request was handled successfully. - [JsonPropertyName("success")] - public bool Success { get; set; } -} - -/// Decision to apply to a pending permission request. -/// Polymorphic base type discriminated by kind. +/// Schema for the `TaskInfo` type. +/// Polymorphic base type discriminated by type. +[Experimental(Diagnostics.Experimental)] [JsonPolymorphic( - TypeDiscriminatorPropertyName = "kind", + TypeDiscriminatorPropertyName = "type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(PermissionDecisionApproveOnce), "approve-once")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSession), "approve-for-session")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocation), "approve-for-location")] -[JsonDerivedType(typeof(PermissionDecisionApprovePermanently), "approve-permanently")] -[JsonDerivedType(typeof(PermissionDecisionReject), "reject")] -[JsonDerivedType(typeof(PermissionDecisionUserNotAvailable), "user-not-available")] -public partial class PermissionDecision +[JsonDerivedType(typeof(TaskInfoAgent), "agent")] +[JsonDerivedType(typeof(TaskInfoShell), "shell")] +public partial class TaskInfo { /// The type discriminator. - [JsonPropertyName("kind")] - public virtual string Kind { get; set; } = string.Empty; + [JsonPropertyName("type")] + public virtual string Type { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionApproveOnce` type. -/// The approve-once variant of . -public partial class PermissionDecisionApproveOnce : PermissionDecision +/// Schema for the `TaskAgentInfo` type. +/// The agent variant of . +[Experimental(Diagnostics.Experimental)] +public partial class TaskInfoAgent : TaskInfo { /// [JsonIgnore] - public override string Kind => "approve-once"; -} + public override string Type => "agent"; -/// The approval to add as a session-scoped rule. -/// Polymorphic base type discriminated by kind. -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "kind", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalCommands), "commands")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalRead), "read")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalWrite), "write")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMcp), "mcp")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMcpSampling), "mcp-sampling")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMemory), "memory")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalCustomTool), "custom-tool")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalExtensionManagement), "extension-management")] -[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess), "extension-permission-access")] -public partial class PermissionDecisionApproveForSessionApproval -{ - /// The type discriminator. - [JsonPropertyName("kind")] - public virtual string Kind { get; set; } = string.Empty; -} + /// ISO 8601 timestamp when the current active period began. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("activeStartedAt")] + public DateTimeOffset? ActiveStartedAt { get; set; } + /// Accumulated active execution time in milliseconds. + [Range((double)0, (double)long.MaxValue)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("activeTimeMs")] + public TimeSpan? ActiveTime { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. -/// The commands variant of . -public partial class PermissionDecisionApproveForSessionApprovalCommands : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "commands"; + /// Type of agent running this task. + [JsonPropertyName("agentType")] + public required string AgentType { get; set; } - /// Command identifiers covered by this approval. - [JsonPropertyName("commandIdentifiers")] - public required IList CommandIdentifiers { get; set; } -} + /// Whether the task is currently in the original sync wait and can be moved to background mode. False once it is already backgrounded, idle, finished, or no longer has a promotable sync waiter. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("canPromoteToBackground")] + public bool? CanPromoteToBackground { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalRead` type. -/// The read variant of . -public partial class PermissionDecisionApproveForSessionApprovalRead : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "read"; -} + /// ISO 8601 timestamp when the task finished. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("completedAt")] + public DateTimeOffset? CompletedAt { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type. -/// The write variant of . -public partial class PermissionDecisionApproveForSessionApprovalWrite : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "write"; -} + /// Short description of the task. + [JsonPropertyName("description")] + public required string Description { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type. -/// The mcp variant of . -public partial class PermissionDecisionApproveForSessionApprovalMcp : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "mcp"; + /// Error message when the task failed. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("error")] + public string? Error { get; set; } - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } + /// Whether task execution is synchronously awaited or managed in the background. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("executionMode")] + public TaskExecutionMode? ExecutionMode { get; set; } - /// MCP tool name, or null to cover every tool on the server. - [JsonPropertyName("toolName")] - public string? ToolName { get; set; } + /// Unique task identifier. + [JsonPropertyName("id")] + public required string Id { get; set; } + + /// ISO 8601 timestamp when the agent entered idle state. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("idleSince")] + public DateTimeOffset? IdleSince { get; set; } + + /// Most recent response text from the agent. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("latestResponse")] + public string? LatestResponse { get; set; } + + /// Model used for the task when specified. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("model")] + public string? Model { get; set; } + + /// Prompt passed to the agent. + [JsonPropertyName("prompt")] + public required string Prompt { get; set; } + + /// Result text from the task when available. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("result")] + public string? Result { get; set; } + + /// ISO 8601 timestamp when the task was started. + [JsonPropertyName("startedAt")] + public required DateTimeOffset StartedAt { get; set; } + + /// Current lifecycle status of the task. + [JsonPropertyName("status")] + public required TaskStatus Status { get; set; } + + /// Tool call ID associated with this agent task. + [JsonPropertyName("toolCallId")] + public required string ToolCallId { get; set; } } -/// Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type. -/// The mcp-sampling variant of . -public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : PermissionDecisionApproveForSessionApproval +/// Schema for the `TaskShellInfo` type. +/// The shell variant of . +[Experimental(Diagnostics.Experimental)] +public partial class TaskInfoShell : TaskInfo { /// [JsonIgnore] - public override string Kind => "mcp-sampling"; + public override string Type => "shell"; - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } -} - -/// Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type. -/// The memory variant of . -public partial class PermissionDecisionApproveForSessionApprovalMemory : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "memory"; -} - -/// Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type. -/// The custom-tool variant of . -public partial class PermissionDecisionApproveForSessionApprovalCustomTool : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "custom-tool"; + /// Whether the shell runs inside a managed PTY session or as an independent background process. + [JsonPropertyName("attachmentMode")] + public required TaskShellInfoAttachmentMode AttachmentMode { get; set; } - /// Custom tool name. - [JsonPropertyName("toolName")] - public required string ToolName { get; set; } -} + /// Whether this shell task can be promoted to background mode. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("canPromoteToBackground")] + public bool? CanPromoteToBackground { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type. -/// The extension-management variant of . -public partial class PermissionDecisionApproveForSessionApprovalExtensionManagement : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "extension-management"; + /// Command being executed. + [JsonPropertyName("command")] + public required string Command { get; set; } - /// Optional operation identifier; when omitted, the approval covers all extension management operations. + /// ISO 8601 timestamp when the task finished. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("operation")] - public string? Operation { get; set; } -} + [JsonPropertyName("completedAt")] + public DateTimeOffset? CompletedAt { get; set; } -/// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` type. -/// The extension-permission-access variant of . -public partial class PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess : PermissionDecisionApproveForSessionApproval -{ - /// - [JsonIgnore] - public override string Kind => "extension-permission-access"; + /// Short description of the task. + [JsonPropertyName("description")] + public required string Description { get; set; } - /// Extension name. - [JsonPropertyName("extensionName")] - public required string ExtensionName { get; set; } -} + /// Whether task execution is synchronously awaited or managed in the background. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("executionMode")] + public TaskExecutionMode? ExecutionMode { get; set; } -/// Schema for the `PermissionDecisionApproveForSession` type. -/// The approve-for-session variant of . -public partial class PermissionDecisionApproveForSession : PermissionDecision -{ - /// - [JsonIgnore] - public override string Kind => "approve-for-session"; + /// Unique task identifier. + [JsonPropertyName("id")] + public required string Id { get; set; } - /// The approval to add as a session-scoped rule. + /// Path to the detached shell log, when available. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("approval")] - public PermissionDecisionApproveForSessionApproval? Approval { get; set; } + [JsonPropertyName("logPath")] + public string? LogPath { get; set; } - /// The URL domain to approve for this session. + /// Process ID when available. + [Range((double)0, (double)4294967295, MinimumIsExclusive = true)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("domain")] - public string? Domain { get; set; } + [JsonPropertyName("pid")] + public long? Pid { get; set; } + + /// ISO 8601 timestamp when the task was started. + [JsonPropertyName("startedAt")] + public required DateTimeOffset StartedAt { get; set; } + + /// Current lifecycle status of the task. + [JsonPropertyName("status")] + public required TaskStatus Status { get; set; } } -/// The approval to persist for this location. -/// Polymorphic base type discriminated by kind. -[JsonPolymorphic( - TypeDiscriminatorPropertyName = "kind", - UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalCommands), "commands")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalRead), "read")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalWrite), "write")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMcp), "mcp")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMcpSampling), "mcp-sampling")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMemory), "memory")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalCustomTool), "custom-tool")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalExtensionManagement), "extension-management")] -[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess), "extension-permission-access")] -public partial class PermissionDecisionApproveForLocationApproval +/// Background tasks currently tracked by the session. +[Experimental(Diagnostics.Experimental)] +public sealed class TaskList { - /// The type discriminator. - [JsonPropertyName("kind")] - public virtual string Kind { get; set; } = string.Empty; + /// Currently tracked tasks. + [JsonPropertyName("tasks")] + public IList Tasks { get => field ??= []; set; } } - -/// Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. -/// The commands variant of . -public partial class PermissionDecisionApproveForLocationApprovalCommands : PermissionDecisionApproveForLocationApproval +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionTasksListRequest { - /// - [JsonIgnore] - public override string Kind => "commands"; - - /// Command identifiers covered by this approval. - [JsonPropertyName("commandIdentifiers")] - public required IList CommandIdentifiers { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionApproveForLocationApprovalRead` type. -/// The read variant of . -public partial class PermissionDecisionApproveForLocationApprovalRead : PermissionDecisionApproveForLocationApproval +/// Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksRefreshResult { - /// - [JsonIgnore] - public override string Kind => "read"; } -/// Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type. -/// The write variant of . -public partial class PermissionDecisionApproveForLocationApprovalWrite : PermissionDecisionApproveForLocationApproval +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionTasksRefreshRequest { - /// - [JsonIgnore] - public override string Kind => "write"; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type. -/// The mcp variant of . -public partial class PermissionDecisionApproveForLocationApprovalMcp : PermissionDecisionApproveForLocationApproval +/// Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). +[Experimental(Diagnostics.Experimental)] +public sealed class TasksWaitForPendingResult { - /// - [JsonIgnore] - public override string Kind => "mcp"; +} - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionTasksWaitForPendingRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// MCP tool name, or null to cover every tool on the server. - [JsonPropertyName("toolName")] - public string? ToolName { get; set; } +/// Progress information for the task, or null when no task with that ID is tracked. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksGetProgressResult +{ + /// Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. + [JsonPropertyName("progress")] + public object? Progress { get; set; } } -/// Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type. -/// The mcp-sampling variant of . -public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : PermissionDecisionApproveForLocationApproval +/// Identifier of the background task to fetch progress for. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksGetProgressRequest { - /// - [JsonIgnore] - public override string Kind => "mcp-sampling"; + /// Task identifier (agent ID or shell ID). + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; - /// MCP server name. - [JsonPropertyName("serverName")] - public required string ServerName { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type. -/// The memory variant of . -public partial class PermissionDecisionApproveForLocationApprovalMemory : PermissionDecisionApproveForLocationApproval +/// The first sync-waiting task that can currently be promoted to background mode. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksGetCurrentPromotableResult { - /// - [JsonIgnore] - public override string Kind => "memory"; + /// The first sync-waiting task (agent first, then shell) that can currently be promoted to background mode. Omitted if no such task exists. The returned task is guaranteed to have executionMode='sync' and canPromoteToBackground=true at the time of the call. + [JsonPropertyName("task")] + public TaskInfo? Task { get; set; } } -/// Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type. -/// The custom-tool variant of . -public partial class PermissionDecisionApproveForLocationApprovalCustomTool : PermissionDecisionApproveForLocationApproval +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionTasksGetCurrentPromotableRequest { - /// - [JsonIgnore] - public override string Kind => "custom-tool"; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Custom tool name. - [JsonPropertyName("toolName")] - public required string ToolName { get; set; } +/// Indicates whether the task was successfully promoted to background mode. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksPromoteToBackgroundResult +{ + /// Whether the task was successfully promoted to background mode. + [JsonPropertyName("promoted")] + public bool Promoted { get; set; } } -/// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type. -/// The extension-management variant of . -public partial class PermissionDecisionApproveForLocationApprovalExtensionManagement : PermissionDecisionApproveForLocationApproval +/// Identifier of the task to promote to background mode. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksPromoteToBackgroundRequest { - /// - [JsonIgnore] - public override string Kind => "extension-management"; + /// Task identifier. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; - /// Optional operation identifier; when omitted, the approval covers all extension management operations. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("operation")] - public string? Operation { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` type. -/// The extension-permission-access variant of . -public partial class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess : PermissionDecisionApproveForLocationApproval +/// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksPromoteCurrentToBackgroundResult { - /// - [JsonIgnore] - public override string Kind => "extension-permission-access"; - - /// Extension name. - [JsonPropertyName("extensionName")] - public required string ExtensionName { get; set; } + /// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. Atomic operation: avoids the race window of getCurrentPromotable + promoteToBackground. + [JsonPropertyName("task")] + public TaskInfo? Task { get; set; } } -/// Schema for the `PermissionDecisionApproveForLocation` type. -/// The approve-for-location variant of . -public partial class PermissionDecisionApproveForLocation : PermissionDecision +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionTasksPromoteCurrentToBackgroundRequest { - /// - [JsonIgnore] - public override string Kind => "approve-for-location"; - - /// The approval to persist for this location. - [JsonPropertyName("approval")] - public required PermissionDecisionApproveForLocationApproval Approval { get; set; } - - /// The location key (git root or cwd) to persist the approval to. - [JsonPropertyName("locationKey")] - public required string LocationKey { get; set; } -} - -/// Schema for the `PermissionDecisionApprovePermanently` type. -/// The approve-permanently variant of . -public partial class PermissionDecisionApprovePermanently : PermissionDecision -{ - /// - [JsonIgnore] - public override string Kind => "approve-permanently"; - - /// The URL domain to approve permanently. - [JsonPropertyName("domain")] - public required string Domain { get; set; } -} - -/// Schema for the `PermissionDecisionReject` type. -/// The reject variant of . -public partial class PermissionDecisionReject : PermissionDecision -{ - /// - [JsonIgnore] - public override string Kind => "reject"; - - /// Optional feedback from the user explaining the denial. - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - [JsonPropertyName("feedback")] - public string? Feedback { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `PermissionDecisionUserNotAvailable` type. -/// The user-not-available variant of . -public partial class PermissionDecisionUserNotAvailable : PermissionDecision +/// Indicates whether the background task was successfully cancelled. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksCancelResult { - /// - [JsonIgnore] - public override string Kind => "user-not-available"; + /// Whether the task was successfully cancelled. + [JsonPropertyName("cancelled")] + public bool Cancelled { get; set; } } -/// Pending permission request ID and the decision to apply (approve/reject and scope). -internal sealed class PermissionDecisionRequest +/// Identifier of the background task to cancel. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksCancelRequest { - /// Request ID of the pending permission request. - [JsonPropertyName("requestId")] - public string RequestId { get; set; } = string.Empty; - - /// Decision to apply to a pending permission request. - [JsonPropertyName("result")] - public PermissionDecision Result { get => field ??= new(); set; } + /// Task identifier. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the operation succeeded. -public sealed class PermissionsSetApproveAllResult +/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksRemoveResult { - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). + [JsonPropertyName("removed")] + public bool Removed { get; set; } } -/// Whether to auto-approve all tool permission requests for the rest of the session. -internal sealed class PermissionsSetApproveAllRequest +/// Identifier of the completed or cancelled task to remove from tracking. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksRemoveRequest { - /// Whether to auto-approve all tool permission requests. - [JsonPropertyName("enabled")] - public bool Enabled { get; set; } + /// Task identifier. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the operation succeeded. -public sealed class PermissionsResetSessionApprovalsResult +/// Indicates whether the message was delivered, with an error message when delivery failed. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksSendMessageResult { - /// Whether the operation succeeded. - [JsonPropertyName("success")] - public bool Success { get; set; } + /// Error message if delivery failed. + [JsonPropertyName("error")] + public string? Error { get; set; } + + /// Whether the message was successfully delivered or steered. + [JsonPropertyName("sent")] + public bool Sent { get; set; } } -/// No parameters; clears all session-scoped tool permission approvals. -internal sealed class PermissionsResetSessionApprovalsRequest +/// Identifier of the target agent task, message content, and optional sender agent ID. +[Experimental(Diagnostics.Experimental)] +internal sealed class TasksSendMessageRequest { + /// Agent ID of the sender, if sent on behalf of another agent. + [JsonPropertyName("fromAgentId")] + public string? FromAgentId { get; set; } + + /// Agent task identifier. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + + /// Message content to send to the agent. + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; + /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Identifier of the spawned process, used to correlate streamed output and exit notifications. -public sealed class ShellExecResult +/// Schema for the `Skill` type. +[Experimental(Diagnostics.Experimental)] +public sealed class Skill { - /// Unique identifier for tracking streamed output. - [JsonPropertyName("processId")] - public string ProcessId { get; set; } = string.Empty; -} + /// Description of what the skill does. + [JsonPropertyName("description")] + public string Description { get; set; } = string.Empty; -/// Shell command to run, with optional working directory and timeout in milliseconds. -internal sealed class ShellExecRequest -{ - /// Shell command to execute. - [JsonPropertyName("command")] - public string Command { get; set; } = string.Empty; + /// Whether the skill is currently enabled. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } - /// Working directory (defaults to session working directory). - [JsonPropertyName("cwd")] - public string? Cwd { get; set; } + /// Unique identifier for the skill. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Absolute path to the skill file. + [JsonPropertyName("path")] + public string? Path { get; set; } - /// Timeout in milliseconds (default: 30000). - [Range((double)0, (double)long.MaxValue)] - [JsonConverter(typeof(MillisecondsTimeSpanConverter))] - [JsonPropertyName("timeout")] - public TimeSpan? Timeout { get; set; } + /// Name of the plugin that provides the skill, when source is 'plugin'. + [JsonPropertyName("pluginName")] + public string? PluginName { get; set; } + + /// Source location type (e.g., project, personal-copilot, plugin, builtin). + [JsonPropertyName("source")] + public SkillSource Source { get; set; } + + /// Whether the skill can be invoked by the user as a slash command. + [JsonPropertyName("userInvocable")] + public bool UserInvocable { get; set; } } -/// Indicates whether the signal was delivered; false if the process was unknown or already exited. -public sealed class ShellKillResult +/// Skills available to the session, with their enabled state. +[Experimental(Diagnostics.Experimental)] +public sealed class SkillList { - /// Whether the signal was sent successfully. - [JsonPropertyName("killed")] - public bool Killed { get; set; } + /// Available skills. + [JsonPropertyName("skills")] + public IList Skills { get => field ??= []; set; } } -/// Identifier of a process previously returned by "shell.exec" and the signal to send. -internal sealed class ShellKillRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionSkillsListRequest { - /// Process identifier returned by shell.exec. - [JsonPropertyName("processId")] - public string ProcessId { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; - - /// Signal to send (default: SIGTERM). - [JsonPropertyName("signal")] - public ShellKillSignal? Signal { get; set; } } -/// Post-compaction context window usage breakdown. +/// Schema for the `SkillsInvokedSkill` type. [Experimental(Diagnostics.Experimental)] -public sealed class HistoryCompactContextWindow +public sealed class SkillsInvokedSkill { - /// Token count from non-system messages (user, assistant, tool). - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("conversationTokens")] - public long? ConversationTokens { get; set; } - - /// Current total tokens in the context window (system + conversation + tool definitions). - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("currentTokens")] - public long CurrentTokens { get; set; } + /// Tools that should be auto-approved when this skill is active, captured at invocation time. + [JsonPropertyName("allowedTools")] + public IList? AllowedTools { get; set; } - /// Current number of messages in the conversation. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("messagesLength")] - public long MessagesLength { get; set; } + /// Full content of the skill file. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; - /// Token count from system message(s). + /// Turn number when the skill was invoked. [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("systemTokens")] - public long? SystemTokens { get; set; } + [JsonPropertyName("invokedAtTurn")] + public long InvokedAtTurn { get; set; } - /// Maximum token count for the model's context window. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("tokenLimit")] - public long TokenLimit { get; set; } + /// Unique identifier for the skill. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Token count from tool definitions. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("toolDefinitionsTokens")] - public long? ToolDefinitionsTokens { get; set; } + /// Path to the SKILL.md file. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; } -/// Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. +/// Skills invoked during this session, ordered by invocation time (most recent last). [Experimental(Diagnostics.Experimental)] -public sealed class HistoryCompactResult +public sealed class SkillsGetInvokedResult { - /// Post-compaction context window usage breakdown. - [JsonPropertyName("contextWindow")] - public HistoryCompactContextWindow? ContextWindow { get; set; } - - /// Number of messages removed during compaction. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("messagesRemoved")] - public long MessagesRemoved { get; set; } - - /// Whether compaction completed successfully. - [JsonPropertyName("success")] - public bool Success { get; set; } - - /// Number of tokens freed by compaction. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("tokensRemoved")] - public long TokensRemoved { get; set; } + /// Skills invoked during this session, ordered by invocation time (most recent last). + [JsonPropertyName("skills")] + public IList Skills { get => field ??= []; set; } } /// Identifies the target session. [Experimental(Diagnostics.Experimental)] -internal sealed class SessionHistoryCompactRequest +internal sealed class SessionSkillsGetInvokedRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Number of events that were removed by the truncation. +/// Name of the skill to enable for the session. [Experimental(Diagnostics.Experimental)] -public sealed class HistoryTruncateResult +internal sealed class SkillsEnableRequest { - /// Number of events that were removed. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("eventsRemoved")] - public long EventsRemoved { get; set; } -} - -/// Identifier of the event to truncate to; this event and all later events are removed. -[Experimental(Diagnostics.Experimental)] -internal sealed class HistoryTruncateRequest -{ - /// Event ID to truncate to. This event and all events after it are removed from the session. - [JsonPropertyName("eventId")] - public string EventId { get; set; } = string.Empty; + /// Name of the skill to enable. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Aggregated code change metrics. +/// Name of the skill to disable for the session. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsCodeChanges +internal sealed class SkillsDisableRequest { - /// Number of distinct files modified. - [JsonPropertyName("filesModifiedCount")] - public long FilesModifiedCount { get; set; } - - /// Total lines of code added. - [JsonPropertyName("linesAdded")] - public long LinesAdded { get; set; } + /// Name of the skill to disable. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Total lines of code removed. - [JsonPropertyName("linesRemoved")] - public long LinesRemoved { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Request count and cost metrics for this model. +/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsModelMetricRequests +public sealed class SkillsLoadDiagnostics { - /// User-initiated premium request cost (with multiplier applied). - [JsonPropertyName("cost")] - public double Cost { get; set; } + /// Errors emitted while loading skills (e.g. skills that failed to load entirely). + [JsonPropertyName("errors")] + public IList Errors { get => field ??= []; set; } - /// Number of API requests made with this model. - [JsonPropertyName("count")] - public long Count { get; set; } + /// Warnings emitted while loading skills (e.g. skills that loaded but had issues). + [JsonPropertyName("warnings")] + public IList Warnings { get => field ??= []; set; } } -/// Schema for the `UsageMetricsModelMetricTokenDetail` type. +/// Identifies the target session. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsModelMetricTokenDetail +internal sealed class SessionSkillsReloadRequest { - /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("tokenCount")] - public long TokenCount { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Token usage metrics for this model. +/// Identifies the target session. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsModelMetricUsage +internal sealed class SessionSkillsEnsureLoadedRequest { - /// Total tokens read from prompt cache. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("cacheReadTokens")] - public long CacheReadTokens { get; set; } - - /// Total tokens written to prompt cache. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("cacheWriteTokens")] - public long CacheWriteTokens { get; set; } - - /// Total input tokens consumed. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("inputTokens")] - public long InputTokens { get; set; } - - /// Total output tokens produced. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("outputTokens")] - public long OutputTokens { get; set; } - - /// Total output tokens used for reasoning. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("reasoningTokens")] - public long? ReasoningTokens { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Schema for the `UsageMetricsModelMetric` type. +/// Schema for the `McpServer` type. [Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsModelMetric +public sealed class McpServer { - /// Request count and cost metrics for this model. - [JsonPropertyName("requests")] - public UsageMetricsModelMetricRequests Requests { get => field ??= new(); set; } - - /// Token count details per type. - [JsonPropertyName("tokenDetails")] - public IDictionary? TokenDetails { get; set; } + /// Error message if the server failed to connect. + [JsonPropertyName("error")] + public string? Error { get; set; } - /// Accumulated nano-AI units cost for this model. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("totalNanoAiu")] - public long? TotalNanoAiu { get; set; } + /// Server name (config key). + [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Token usage metrics for this model. - [JsonPropertyName("usage")] - public UsageMetricsModelMetricUsage Usage { get => field ??= new(); set; } -} + /// Configuration source: user, workspace, plugin, or builtin. + [JsonPropertyName("source")] + public McpServerSource? Source { get; set; } -/// Schema for the `UsageMetricsTokenDetail` type. -[Experimental(Diagnostics.Experimental)] -public sealed class UsageMetricsTokenDetail -{ - /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("tokenCount")] - public long TokenCount { get; set; } + /// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured. + [JsonPropertyName("status")] + public McpServerStatus Status { get; set; } } -/// Accumulated session usage metrics, including premium request cost, token counts, model breakdown, and code-change totals. +/// MCP servers configured for the session, with their connection status. [Experimental(Diagnostics.Experimental)] -public sealed class UsageGetMetricsResult +public sealed class McpServerList { - /// Aggregated code change metrics. - [JsonPropertyName("codeChanges")] - public UsageMetricsCodeChanges CodeChanges { get => field ??= new(); set; } - - /// Currently active model identifier. - [JsonPropertyName("currentModel")] - public string? CurrentModel { get; set; } - - /// Input tokens from the most recent main-agent API call. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("lastCallInputTokens")] - public long LastCallInputTokens { get; set; } - - /// Output tokens from the most recent main-agent API call. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("lastCallOutputTokens")] - public long LastCallOutputTokens { get; set; } - - /// Per-model token and request metrics, keyed by model identifier. - [JsonPropertyName("modelMetrics")] - public IDictionary ModelMetrics { get => field ??= new Dictionary(); set; } - - /// Session start timestamp (epoch milliseconds). - [JsonPropertyName("sessionStartTime")] - public long SessionStartTime { get; set; } - - /// Session-wide per-token-type accumulated token counts. - [JsonPropertyName("tokenDetails")] - public IDictionary? TokenDetails { get; set; } - - /// Total time spent in model API calls (milliseconds). - [Range(0, double.MaxValue)] - [JsonConverter(typeof(MillisecondsTimeSpanConverter))] - [JsonPropertyName("totalApiDurationMs")] - public TimeSpan TotalApiDuration { get; set; } - - /// Session-wide accumulated nano-AI units cost. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("totalNanoAiu")] - public long? TotalNanoAiu { get; set; } - - /// Total user-initiated premium request cost across all models (may be fractional due to multipliers). - [JsonPropertyName("totalPremiumRequestCost")] - public double TotalPremiumRequestCost { get; set; } - - /// Raw count of user-initiated API requests. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("totalUserRequests")] - public long TotalUserRequests { get; set; } + /// Configured MCP servers. + [JsonPropertyName("servers")] + public IList Servers { get => field ??= []; set; } } /// Identifies the target session. [Experimental(Diagnostics.Experimental)] -internal sealed class SessionUsageGetMetricsRequest +internal sealed class SessionMcpListRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// GitHub URL for the session and a flag indicating whether remote steering is enabled. +/// Name of the MCP server to enable for the session. [Experimental(Diagnostics.Experimental)] -public sealed class RemoteEnableResult +internal sealed class McpEnableRequest { - /// Whether remote steering is enabled. - [JsonPropertyName("remoteSteerable")] - public bool RemoteSteerable { get; set; } + /// Name of the MCP server to enable. + [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] + [JsonPropertyName("serverName")] + public string ServerName { get; set; } = string.Empty; - /// GitHub frontend URL for this session. - [Url] - [StringSyntax(StringSyntaxAttribute.Uri)] - [JsonPropertyName("url")] - public string? Url { get; set; } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } -/// Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. +/// Name of the MCP server to disable for the session. [Experimental(Diagnostics.Experimental)] -internal sealed class RemoteEnableRequest +internal sealed class McpDisableRequest { - /// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. - [JsonPropertyName("mode")] - public RemoteSessionMode? Mode { get; set; } + /// Name of the MCP server to disable. + [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] + [JsonPropertyName("serverName")] + public string ServerName { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] @@ -3026,3280 +3316,8591 @@ internal sealed class RemoteEnableRequest /// Identifies the target session. [Experimental(Diagnostics.Experimental)] -internal sealed class SessionRemoteDisableRequest +internal sealed class SessionMcpReloadRequest { /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Describes a filesystem error. -public sealed class SessionFsError +/// MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. +[Experimental(Diagnostics.Experimental)] +public sealed class McpExecuteSamplingResult { - /// Error classification. - [JsonPropertyName("code")] - public SessionFsErrorCode Code { get; set; } - - /// Free-form detail about the error, for logging/diagnostics. - [JsonPropertyName("message")] - public string? Message { get; set; } } -/// File content as a UTF-8 string, or a filesystem error if the read failed. -public sealed class SessionFsReadFileResult +/// Outcome of an MCP sampling execution: success result, failure error, or cancellation. +[Experimental(Diagnostics.Experimental)] +public sealed class McpSamplingExecutionResult { - /// File content as UTF-8 string. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; + /// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. + [JsonPropertyName("action")] + public McpSamplingExecutionAction Action { get; set; } - /// Describes a filesystem error. + /// Error description, present when action='failure'. [JsonPropertyName("error")] - public SessionFsError? Error { get; set; } + public string? Error { get; set; } + + /// MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. + [JsonPropertyName("result")] + public McpExecuteSamplingResult? Result { get; set; } } -/// Path of the file to read from the client-provided session filesystem. -public sealed class SessionFsReadFileRequest +/// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. +[Experimental(Diagnostics.Experimental)] +public sealed class McpExecuteSamplingRequest { - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; +} + +/// Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. +[Experimental(Diagnostics.Experimental)] +internal sealed class McpExecuteSamplingParams +{ + /// The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate the inference with the originating MCP request for telemetry; this is distinct from `requestId` (which is the schema-level cancellation handle). + [JsonPropertyName("mcpRequestId")] + public object McpRequestId { get; set; } = null!; + + /// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. + [JsonPropertyName("request")] + public McpExecuteSamplingRequest Request { get => field ??= new(); set; } + + /// Caller-provided unique identifier for this sampling execution. Use this same ID with cancelSamplingExecution to cancel the in-flight call. Must be unique within the session for the lifetime of the call. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; + + /// Name of the MCP server that initiated the sampling request. + [JsonPropertyName("serverName")] + public string ServerName { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// File path, content to write, and optional mode for the client-provided session filesystem. -public sealed class SessionFsWriteFileRequest +/// Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. +[Experimental(Diagnostics.Experimental)] +public sealed class McpCancelSamplingExecutionResult { - /// Content to write. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; - - /// Optional POSIX-style mode for newly created files. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("mode")] - public long? Mode { get; set; } + /// True if an in-flight execution with the given requestId was found and signalled to cancel. False when no such execution is in flight (already completed, never started, or cancelled by another caller). + [JsonPropertyName("cancelled")] + public bool Cancelled { get; set; } +} - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; +/// The requestId previously passed to executeSampling that should be cancelled. +[Experimental(Diagnostics.Experimental)] +internal sealed class McpCancelSamplingExecutionParams +{ + /// The requestId previously passed to executeSampling that should be cancelled. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// File path, content to append, and optional mode for the client-provided session filesystem. -public sealed class SessionFsAppendFileRequest +/// Env-value mode recorded on the session after the update. +[Experimental(Diagnostics.Experimental)] +public sealed class McpSetEnvValueModeResult { - /// Content to append. - [JsonPropertyName("content")] - public string Content { get; set; } = string.Empty; - - /// Optional POSIX-style mode for newly created files. - [Range((double)0, (double)long.MaxValue)] + /// Mode recorded on the session after the update. [JsonPropertyName("mode")] - public long? Mode { get; set; } + public McpSetEnvValueModeDetails Mode { get; set; } +} - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; +/// Mode controlling how MCP server env values are resolved (`direct` or `indirect`). +[Experimental(Diagnostics.Experimental)] +internal sealed class McpSetEnvValueModeParams +{ + /// How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". + [JsonPropertyName("mode")] + public McpSetEnvValueModeDetails Mode { get; set; } /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Indicates whether the requested path exists in the client-provided session filesystem. -public sealed class SessionFsExistsResult +/// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). +[Experimental(Diagnostics.Experimental)] +public sealed class McpRemoveGitHubResult { - /// Whether the path exists. - [JsonPropertyName("exists")] - public bool Exists { get; set; } + /// True when the auto-managed `github` MCP server was removed; false when no removal happened (e.g. user has explicitly configured a `github` server, or the server was not registered). + [JsonPropertyName("removed")] + public bool Removed { get; set; } } -/// Path to test for existence in the client-provided session filesystem. -public sealed class SessionFsExistsRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionMcpRemoveGitHubRequest { - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Filesystem metadata for the requested path, or a filesystem error if the stat failed. -public sealed class SessionFsStatResult +/// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. +[Experimental(Diagnostics.Experimental)] +public sealed class McpOauthLoginResult { - /// ISO 8601 timestamp of creation. - [JsonPropertyName("birthtime")] - public DateTimeOffset Birthtime { get; set; } - - /// Describes a filesystem error. - [JsonPropertyName("error")] - public SessionFsError? Error { get; set; } - - /// Whether the path is a directory. - [JsonPropertyName("isDirectory")] - public bool IsDirectory { get; set; } + /// URL the caller should open in a browser to complete OAuth. Omitted when cached tokens were still valid and no browser interaction was needed — the server is already reconnected in that case. When present, the runtime starts the callback listener before returning and continues the flow in the background; completion is signaled via session.mcp_server_status_changed. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("authorizationUrl")] + public string? AuthorizationUrl { get; set; } +} - /// Whether the path is a file. - [JsonPropertyName("isFile")] - public bool IsFile { get; set; } +/// Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. +[Experimental(Diagnostics.Experimental)] +internal sealed class McpOauthLoginRequest +{ + /// Optional override for the body text shown on the OAuth loopback callback success page. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass surface-specific copy telling the user where to return. + [JsonPropertyName("callbackSuccessMessage")] + public string? CallbackSuccessMessage { get; set; } - /// ISO 8601 timestamp of last modification. - [JsonPropertyName("mtime")] - public DateTimeOffset Mtime { get; set; } + /// Optional override for the OAuth client display name shown on the consent screen. Applies to newly registered dynamic clients only — existing registrations keep the name they were created with. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass their own surface-specific label so the consent screen matches the product the user sees. + [JsonPropertyName("clientName")] + public string? ClientName { get; set; } - /// File size in bytes. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("size")] - public long Size { get; set; } -} + /// When true, clears any cached OAuth token for the server and runs a full new authorization. Use when the user explicitly wants to switch accounts or believes their session is stuck. + [JsonPropertyName("forceReauth")] + public bool? ForceReauth { get; set; } -/// Path whose metadata should be returned from the client-provided session filesystem. -public sealed class SessionFsStatRequest -{ - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Name of the remote MCP server to authenticate. + [RegularExpression("^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Safe for generated string properties: JSON Schema minLength/maxLength map to string length validation, not reflection over trimmed Count members")] + [MinLength(1)] + [JsonPropertyName("serverName")] + public string ServerName { get; set; } = string.Empty; /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. -public sealed class SessionFsMkdirRequest +/// Schema for the `Plugin` type. +[Experimental(Diagnostics.Experimental)] +public sealed class Plugin { - /// Optional POSIX-style mode for newly created directories. - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("mode")] - public long? Mode { get; set; } + /// Whether the plugin is currently enabled. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Marketplace the plugin came from. + [JsonPropertyName("marketplace")] + public string Marketplace { get; set; } = string.Empty; - /// Create parent directories as needed. - [JsonPropertyName("recursive")] - public bool? Recursive { get; set; } + /// Plugin name. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Installed version. + [JsonPropertyName("version")] + public string? Version { get; set; } } -/// Names of entries in the requested directory, or a filesystem error if the read failed. -public sealed class SessionFsReaddirResult +/// Plugins installed for the session, with their enabled state and version metadata. +[Experimental(Diagnostics.Experimental)] +public sealed class PluginList { - /// Entry names in the directory. - [JsonPropertyName("entries")] - public IList Entries { get => field ??= []; set; } - - /// Describes a filesystem error. - [JsonPropertyName("error")] - public SessionFsError? Error { get; set; } + /// Installed plugins. + [JsonPropertyName("plugins")] + public IList Plugins { get => field ??= []; set; } } -/// Directory path whose entries should be listed from the client-provided session filesystem. -public sealed class SessionFsReaddirRequest +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionPluginsListRequest { - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; - /// Target session identifier. [JsonPropertyName("sessionId")] public string SessionId { get; set; } = string.Empty; } -/// Schema for the `SessionFsReaddirWithTypesEntry` type. -public sealed class SessionFsReaddirWithTypesEntry +/// Indicates whether the session options patch was applied successfully. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionUpdateOptionsResult { - /// Entry name. + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} + +/// Schema for the `SessionInstalledPlugin` type. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionInstalledPlugin +{ + /// Path where the plugin is cached locally. + [JsonPropertyName("cache_path")] + public string? CachePath { get; set; } + + /// Whether the plugin is currently enabled. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } + + /// Installation timestamp (ISO-8601). + [JsonPropertyName("installed_at")] + public string InstalledAt { get; set; } = string.Empty; + + /// Marketplace the plugin came from (empty string for direct repo installs). + [JsonPropertyName("marketplace")] + public string Marketplace { get; set; } = string.Empty; + + /// Plugin name. [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; - /// Entry type. - [JsonPropertyName("type")] - public SessionFsReaddirWithTypesEntryType Type { get; set; } + /// Source descriptor for direct repo installs (when marketplace is empty). + [JsonPropertyName("source")] + public object? Source { get; set; } + + /// Installed version, if known. + [JsonPropertyName("version")] + public string? Version { get; set; } } -/// Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. -public sealed class SessionFsReaddirWithTypesResult +/// Patch of mutable session options to apply to the running session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionUpdateOptionsParams { - /// Directory entries with type information. - [JsonPropertyName("entries")] - public IList Entries { get => field ??= []; set; } + /// Additional content-exclusion policies to merge into the session's policy set. Opaque shape; see `ContentExclusionApiResponse` in the runtime. + [JsonPropertyName("additionalContentExclusionPolicies")] + public IList? AdditionalContentExclusionPolicies { get; set; } - /// Describes a filesystem error. - [JsonPropertyName("error")] - public SessionFsError? Error { get; set; } -} + /// Runtime context discriminator (e.g., `cli`, `actions`). + [JsonPropertyName("agentContext")] + public string? AgentContext { get; set; } -/// Directory path whose entries (with type information) should be listed from the client-provided session filesystem. -public sealed class SessionFsReaddirWithTypesRequest -{ - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Whether to disable the `ask_user` tool (encourages autonomous behavior). + [JsonPropertyName("askUserDisabled")] + public bool? AskUserDisabled { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Allowlist of tool names available to this session. + [JsonPropertyName("availableTools")] + public IList? AvailableTools { get; set; } -/// Path to remove from the client-provided session filesystem, with options for recursive removal and force. -public sealed class SessionFsRmRequest -{ - /// Ignore errors if the path does not exist. - [JsonPropertyName("force")] - public bool? Force { get; set; } + /// Identifier of the client driving the session. + [JsonPropertyName("clientName")] + public string? ClientName { get; set; } - /// Path using SessionFs conventions. - [JsonPropertyName("path")] - public string Path { get; set; } = string.Empty; + /// Whether to include the `Co-authored-by` trailer in commit messages. + [JsonPropertyName("coauthorEnabled")] + public bool? CoauthorEnabled { get; set; } - /// Remove directories and their contents recursively. - [JsonPropertyName("recursive")] - public bool? Recursive { get; set; } + /// Whether to allow auto-mode continuation across turns. + [JsonPropertyName("continueOnAutoMode")] + public bool? ContinueOnAutoMode { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Override URL for the Copilot API endpoint. + [JsonPropertyName("copilotUrl")] + public string? CopilotUrl { get; set; } -/// Source and destination paths for renaming or moving an entry in the client-provided session filesystem. -public sealed class SessionFsRenameRequest -{ - /// Destination path using SessionFs conventions. - [JsonPropertyName("dest")] - public string Dest { get; set; } = string.Empty; + /// Whether to default custom agents to local-only execution. + [JsonPropertyName("customAgentsLocalOnly")] + public bool? CustomAgentsLocalOnly { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; + /// Instruction source IDs to exclude from the system prompt. + [JsonPropertyName("disabledInstructionSources")] + public IList? DisabledInstructionSources { get; set; } - /// Source path using SessionFs conventions. - [JsonPropertyName("src")] - public string Src { get; set; } = string.Empty; -} + /// Skill IDs that should be excluded from this session. + [JsonPropertyName("disabledSkills")] + public IList? DisabledSkills { get; set; } -/// Query results including rows, columns, and rows affected, or a filesystem error if execution failed. -public sealed class SessionFsSqliteQueryResult -{ - /// Column names from the result set. - [JsonPropertyName("columns")] - public IList Columns { get => field ??= []; set; } + /// Whether to discover custom instructions on demand after successful file views (AGENTS.md / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. + [JsonPropertyName("enableOnDemandInstructionDiscovery")] + public bool? EnableOnDemandInstructionDiscovery { get; set; } - /// Describes a filesystem error. - [JsonPropertyName("error")] - public SessionFsError? Error { get; set; } + /// Whether to surface reasoning-summary events from the model. + [JsonPropertyName("enableReasoningSummaries")] + public bool? EnableReasoningSummaries { get; set; } - /// Last inserted row ID (for INSERT). - [JsonPropertyName("lastInsertRowid")] - public double? LastInsertRowid { get; set; } + /// Whether shell-script safety heuristics are enabled. + [JsonPropertyName("enableScriptSafety")] + public bool? EnableScriptSafety { get; set; } - /// For SELECT: array of row objects. For others: empty array. - [JsonPropertyName("rows")] - public IList> Rows { get => field ??= []; set; } + /// Whether to stream model responses. + [JsonPropertyName("enableStreaming")] + public bool? EnableStreaming { get; set; } - /// Number of rows affected (for INSERT/UPDATE/DELETE). - [Range((double)0, (double)long.MaxValue)] - [JsonPropertyName("rowsAffected")] - public long RowsAffected { get; set; } -} + /// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). + [JsonPropertyName("envValueMode")] + public OptionsUpdateEnvValueMode? EnvValueMode { get; set; } -/// SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. -public sealed class SessionFsSqliteQueryRequest -{ - /// Optional named bind parameters. - [JsonPropertyName("params")] - public IDictionary? Params { get; set; } + /// Override directory for the session-events log. When unset, the runtime's default events log directory is used. + [JsonPropertyName("eventsLogDirectory")] + public string? EventsLogDirectory { get; set; } - /// SQL query to execute. - [JsonPropertyName("query")] - public string Query { get; set; } = string.Empty; + /// Denylist of tool names for this session. + [JsonPropertyName("excludedTools")] + public IList? ExcludedTools { get; set; } - /// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected). - [JsonPropertyName("queryType")] - public SessionFsSqliteQueryType QueryType { get; set; } + /// Map of feature-flag IDs to their boolean enabled state. + [JsonPropertyName("featureFlags")] + public IDictionary? FeatureFlags { get; set; } - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Full set of installed plugins for the session. Replaces the existing list; the runtime invalidates the skills cache only when the list materially changes. + [JsonPropertyName("installedPlugins")] + public IList? InstalledPlugins { get; set; } -/// Indicates whether the per-session SQLite database already exists. -public sealed class SessionFsSqliteExistsResult -{ - /// Whether the session database already exists. - [JsonPropertyName("exists")] - public bool Exists { get; set; } -} + /// Stable integration identifier used for analytics and rate-limit attribution. + [JsonPropertyName("integrationId")] + public string? IntegrationId { get; set; } -/// Identifies the target session. -public sealed class SessionFsSqliteExistsRequest -{ - /// Target session identifier. - [JsonPropertyName("sessionId")] - public string SessionId { get; set; } = string.Empty; -} + /// Whether experimental capabilities are enabled. + [JsonPropertyName("isExperimentalMode")] + public bool? IsExperimentalMode { get; set; } -/// Model capability category for grouping in the model picker. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ModelPickerCategory : IEquatable -{ - private readonly string? _value; + /// Whether interactive shell sessions are logged. + [JsonPropertyName("logInteractiveShells")] + public bool? LogInteractiveShells { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ModelPickerCategory(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Identifier sent to LSP-style integrations. + [JsonPropertyName("lspClientName")] + public string? LspClientName { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the per-session schedule registry; this flag only controls tool exposure (typically gated to staff users). + [JsonPropertyName("manageScheduleEnabled")] + public bool? ManageScheduleEnabled { get; set; } - /// Gets the lightweight value. - public static ModelPickerCategory Lightweight { get; } = new("lightweight"); + /// The model ID to use for assistant turns. + [JsonPropertyName("model")] + public string? Model { get; set; } - /// Gets the versatile value. - public static ModelPickerCategory Versatile { get; } = new("versatile"); + /// Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the runtime. + [JsonPropertyName("provider")] + public object? Provider { get; set; } - /// Gets the powerful value. - public static ModelPickerCategory Powerful { get; } = new("powerful"); + /// Reasoning effort for the selected model (model-defined enum). + [JsonPropertyName("reasoningEffort")] + public string? ReasoningEffort { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ModelPickerCategory left, ModelPickerCategory right) => left.Equals(right); + /// Whether the session is running in an interactive UI. + [JsonPropertyName("runningInInteractiveMode")] + public bool? RunningInInteractiveMode { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ModelPickerCategory left, ModelPickerCategory right) => !(left == right); + /// Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. + [JsonPropertyName("sandboxConfig")] + public object? SandboxConfig { get; set; } - /// - public override bool Equals(object? obj) => obj is ModelPickerCategory other && Equals(other); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// - public bool Equals(ModelPickerCategory other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Shell init profile (`None` or `NonInteractive`). + [JsonPropertyName("shellInitProfile")] + public string? ShellInitProfile { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Per-shell process flags (e.g., `pwsh` arguments). + [JsonPropertyName("shellProcessFlags")] + public IList? ShellProcessFlags { get; set; } - /// - public override string ToString() => Value; + /// Additional directories to search for skills. + [JsonPropertyName("skillDirectories")] + public IList? SkillDirectories { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ModelPickerCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Whether to skip loading custom instruction sources. + [JsonPropertyName("skipCustomInstructions")] + public bool? SkipCustomInstructions { get; set; } - /// - public override void Write(Utf8JsonWriter writer, ModelPickerCategory value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); - } - } -} + /// Optional path for trajectory output. + [JsonPropertyName("trajectoryFile")] + public string? TrajectoryFile { get; set; } + /// Absolute working-directory path for shell tools. + [JsonPropertyName("workingDirectory")] + public string? WorkingDirectory { get; set; } +} -/// Relative cost tier for token-based billing users. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ModelPickerPriceCategory : IEquatable +/// Parameters for (re)loading the merged LSP configuration set. +[Experimental(Diagnostics.Experimental)] +internal sealed class LspInitializeRequest { - private readonly string? _value; + /// Force re-initialization even when LSP configs were already loaded for the working directory. + [JsonPropertyName("force")] + public bool? Force { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ModelPickerPriceCategory(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Git root used as the boundary when traversing for project-level LSP configs (supports monorepos). + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// Gets the low value. - public static ModelPickerPriceCategory Low { get; } = new("low"); + /// Working directory used to load project-level LSP configs. Defaults to the session working directory when omitted. + [JsonPropertyName("workingDirectory")] + public string? WorkingDirectory { get; set; } +} - /// Gets the medium value. - public static ModelPickerPriceCategory Medium { get; } = new("medium"); +/// Schema for the `Extension` type. +[Experimental(Diagnostics.Experimental)] +public sealed class Extension +{ + /// Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper'). + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; - /// Gets the high value. - public static ModelPickerPriceCategory High { get; } = new("high"); + /// Extension name (directory name). + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Gets the very_high value. - public static ModelPickerPriceCategory VeryHigh { get; } = new("very_high"); + /// Process ID if the extension is running. + [Range((double)0, (double)4294967295, MinimumIsExclusive = true)] + [JsonPropertyName("pid")] + public long? Pid { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ModelPickerPriceCategory left, ModelPickerPriceCategory right) => left.Equals(right); + /// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/). + [JsonPropertyName("source")] + public ExtensionSource Source { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ModelPickerPriceCategory left, ModelPickerPriceCategory right) => !(left == right); + /// Current status: running, disabled, failed, or starting. + [JsonPropertyName("status")] + public ExtensionStatus Status { get; set; } +} - /// - public override bool Equals(object? obj) => obj is ModelPickerPriceCategory other && Equals(other); +/// Extensions discovered for the session, with their current status. +[Experimental(Diagnostics.Experimental)] +public sealed class ExtensionList +{ + /// Discovered extensions and their current status. + [JsonPropertyName("extensions")] + public IList Extensions { get => field ??= []; set; } +} - /// - public bool Equals(ModelPickerPriceCategory other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionExtensionsListRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Source-qualified extension identifier to enable for the session. +[Experimental(Diagnostics.Experimental)] +internal sealed class ExtensionsEnableRequest +{ + /// Source-qualified extension ID to enable. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; - /// - public override string ToString() => Value; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ModelPickerPriceCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } +/// Source-qualified extension identifier to disable for the session. +[Experimental(Diagnostics.Experimental)] +internal sealed class ExtensionsDisableRequest +{ + /// Source-qualified extension ID to disable. + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, ModelPickerPriceCategory value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionExtensionsReloadRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} -/// Current policy state for this model. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ModelPolicyState : IEquatable +/// Indicates whether the external tool call result was handled successfully. +public sealed class HandlePendingToolCallResult { - private readonly string? _value; + /// Whether the tool call result was handled successfully. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ModelPolicyState(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } +/// Pending external tool call request ID, with the tool result or an error describing why it failed. +internal sealed class HandlePendingToolCallRequest +{ + /// Error message if the tool call failed. + [JsonPropertyName("error")] + public string? Error { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Request ID of the pending tool call. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// Gets the enabled value. - public static ModelPolicyState Enabled { get; } = new("enabled"); - - /// Gets the disabled value. - public static ModelPolicyState Disabled { get; } = new("disabled"); - - /// Gets the unconfigured value. - public static ModelPolicyState Unconfigured { get; } = new("unconfigured"); - - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ModelPolicyState left, ModelPolicyState right) => left.Equals(right); + /// Tool call result (string or expanded result object). + [JsonPropertyName("result")] + public object? Result { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ModelPolicyState left, ModelPolicyState right) => !(left == right); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override bool Equals(object? obj) => obj is ModelPolicyState other && Equals(other); +/// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. +public sealed class ToolsInitializeAndValidateResult +{ +} - /// - public bool Equals(ModelPolicyState other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Identifies the target session. +internal sealed class SessionToolsInitializeAndValidateRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Optional unstructured input hint. +public sealed class SlashCommandInput +{ + /// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). + [JsonPropertyName("completion")] + public SlashCommandInputCompletion? Completion { get; set; } - /// - public override string ToString() => Value; + /// Hint to display when command input has not been provided. + [JsonPropertyName("hint")] + public string Hint { get; set; } = string.Empty; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ModelPolicyState Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// When true, clients should pass the full text after the command name as a single argument rather than splitting on whitespace. + [JsonPropertyName("preserveMultilineInput")] + public bool? PreserveMultilineInput { get; set; } - /// - public override void Write(Utf8JsonWriter writer, ModelPolicyState value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); - } - } + /// When true, the command requires non-empty input; clients should render the input hint as required. + [JsonPropertyName("required")] + public bool? Required { get; set; } } - -/// Server transport type: stdio, http, sse, or memory. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct DiscoveredMcpServerType : IEquatable +/// Schema for the `SlashCommandInfo` type. +public sealed class SlashCommandInfo { - private readonly string? _value; + /// Canonical aliases without leading slashes. + [JsonPropertyName("aliases")] + public IList? Aliases { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public DiscoveredMcpServerType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Whether the command may run while an agent turn is active. + [JsonPropertyName("allowDuringAgentExecution")] + public bool AllowDuringAgentExecution { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Human-readable command description. + [JsonPropertyName("description")] + public string Description { get; set; } = string.Empty; - /// Gets the stdio value. - public static DiscoveredMcpServerType Stdio { get; } = new("stdio"); + /// Whether the command is experimental. + [JsonPropertyName("experimental")] + public bool? Experimental { get; set; } - /// Gets the http value. - public static DiscoveredMcpServerType Http { get; } = new("http"); + /// Optional unstructured input hint. + [JsonPropertyName("input")] + public SlashCommandInput? Input { get; set; } - /// Gets the sse value. - public static DiscoveredMcpServerType Sse { get; } = new("sse"); + /// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. + [JsonPropertyName("kind")] + public SlashCommandKind Kind { get; set; } - /// Gets the memory value. - public static DiscoveredMcpServerType Memory { get; } = new("memory"); + /// Canonical command name without a leading slash. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(DiscoveredMcpServerType left, DiscoveredMcpServerType right) => left.Equals(right); +/// Slash commands available in the session, after applying any include/exclude filters. +public sealed class CommandList +{ + /// Commands available in this session. + [JsonPropertyName("commands")] + public IList Commands { get => field ??= []; set; } +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(DiscoveredMcpServerType left, DiscoveredMcpServerType right) => !(left == right); +/// Optional filters controlling which command sources to include in the listing. +public sealed class CommandsListRequest +{ + /// Include runtime built-in commands. + [JsonPropertyName("includeBuiltins")] + public bool? IncludeBuiltins { get; set; } - /// - public override bool Equals(object? obj) => obj is DiscoveredMcpServerType other && Equals(other); + /// Include commands registered by protocol clients, including SDK clients and extensions. + [JsonPropertyName("includeClientCommands")] + public bool? IncludeClientCommands { get; set; } - /// - public bool Equals(DiscoveredMcpServerType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Include enabled user-invocable skills and commands. + [JsonPropertyName("includeSkills")] + public bool? IncludeSkills { get; set; } +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Optional filters controlling which command sources to include in the listing. +internal sealed class CommandsListRequestWithSession +{ + /// Include runtime built-in commands. + [JsonPropertyName("includeBuiltins")] + public bool? IncludeBuiltins { get; set; } - /// - public override string ToString() => Value; + /// Include commands registered by protocol clients, including SDK clients and extensions. + [JsonPropertyName("includeClientCommands")] + public bool? IncludeClientCommands { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override DiscoveredMcpServerType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Include enabled user-invocable skills and commands. + [JsonPropertyName("includeSkills")] + public bool? IncludeSkills { get; set; } - /// - public override void Write(Utf8JsonWriter writer, DiscoveredMcpServerType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } - -/// Path conventions used by this filesystem. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SessionFsSetProviderConventions : IEquatable +/// Result of invoking the slash command (text output, prompt to send to the agent, or completion). +/// Polymorphic base type discriminated by kind. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "kind", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(SlashCommandInvocationResultText), "text")] +[JsonDerivedType(typeof(SlashCommandInvocationResultAgentPrompt), "agent-prompt")] +[JsonDerivedType(typeof(SlashCommandInvocationResultCompleted), "completed")] +public partial class SlashCommandInvocationResult { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SessionFsSetProviderConventions(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// The type discriminator. + [JsonPropertyName("kind")] + public virtual string Kind { get; set; } = string.Empty; +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; - /// Gets the windows value. - public static SessionFsSetProviderConventions Windows { get; } = new("windows"); +/// Schema for the `SlashCommandTextResult` type. +/// The text variant of . +public partial class SlashCommandInvocationResultText : SlashCommandInvocationResult +{ + /// + [JsonIgnore] + public override string Kind => "text"; - /// Gets the posix value. - public static SessionFsSetProviderConventions Posix { get; } = new("posix"); + /// Whether text contains Markdown. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("markdown")] + public bool? Markdown { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionFsSetProviderConventions left, SessionFsSetProviderConventions right) => left.Equals(right); + /// Whether ANSI sequences should be preserved. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("preserveAnsi")] + public bool? PreserveAnsi { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionFsSetProviderConventions left, SessionFsSetProviderConventions right) => !(left == right); + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("runtimeSettingsChanged")] + public bool? RuntimeSettingsChanged { get; set; } - /// - public override bool Equals(object? obj) => obj is SessionFsSetProviderConventions other && Equals(other); + /// Text output for the client to render. + [JsonPropertyName("text")] + public required string Text { get; set; } +} +/// Schema for the `SlashCommandAgentPromptResult` type. +/// The agent-prompt variant of . +public partial class SlashCommandInvocationResultAgentPrompt : SlashCommandInvocationResult +{ /// - public bool Equals(SessionFsSetProviderConventions other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + [JsonIgnore] + public override string Kind => "agent-prompt"; - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Prompt text to display to the user. + [JsonPropertyName("displayPrompt")] + public required string DisplayPrompt { get; set; } - /// - public override string ToString() => Value; + /// Optional target session mode for the agent prompt. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("mode")] + public SessionMode? Mode { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SessionFsSetProviderConventions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Prompt to submit to the agent. + [JsonPropertyName("prompt")] + public required string Prompt { get; set; } - /// - public override void Write(Utf8JsonWriter writer, SessionFsSetProviderConventions value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); - } - } + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("runtimeSettingsChanged")] + public bool? RuntimeSettingsChanged { get; set; } } - -/// Neutral SDK discriminator for the connected remote session kind. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ConnectedRemoteSessionMetadataKind : IEquatable +/// Schema for the `SlashCommandCompletedResult` type. +/// The completed variant of . +public partial class SlashCommandInvocationResultCompleted : SlashCommandInvocationResult { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ConnectedRemoteSessionMetadataKind(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } - - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; - - /// Gets the remote-session value. - public static ConnectedRemoteSessionMetadataKind RemoteSession { get; } = new("remote-session"); + /// + [JsonIgnore] + public override string Kind => "completed"; - /// Gets the coding-agent value. - public static ConnectedRemoteSessionMetadataKind CodingAgent { get; } = new("coding-agent"); + /// Optional user-facing message describing the completed command. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("message")] + public string? Message { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ConnectedRemoteSessionMetadataKind left, ConnectedRemoteSessionMetadataKind right) => left.Equals(right); + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("runtimeSettingsChanged")] + public bool? RuntimeSettingsChanged { get; set; } +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ConnectedRemoteSessionMetadataKind left, ConnectedRemoteSessionMetadataKind right) => !(left == right); +/// Slash command name and optional raw input string to invoke. +internal sealed class CommandsInvokeRequest +{ + /// Raw input after the command name. + [JsonPropertyName("input")] + public string? Input { get; set; } - /// - public override bool Equals(object? obj) => obj is ConnectedRemoteSessionMetadataKind other && Equals(other); + /// Command name. Leading slashes are stripped and the name is matched case-insensitively. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// - public bool Equals(ConnectedRemoteSessionMetadataKind other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Indicates whether the pending client-handled command was completed successfully. +public sealed class CommandsHandlePendingCommandResult +{ + /// Whether the command was handled successfully. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// - public override string ToString() => Value; +/// Pending command request ID and an optional error if the client handler failed. +internal sealed class CommandsHandlePendingCommandRequest +{ + /// Error message if the command handler failed. + [JsonPropertyName("error")] + public string? Error { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ConnectedRemoteSessionMetadataKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Request ID from the command invocation event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, ConnectedRemoteSessionMetadataKind value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Error message produced while executing the command, if any. +public sealed class ExecuteCommandResult +{ + /// Error message produced while executing the command, if any. Omitted when the handler succeeded. + [JsonPropertyName("error")] + public string? Error { get; set; } +} -/// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SessionLogLevel : IEquatable +/// Slash command name and argument string to execute synchronously. +internal sealed class ExecuteCommandParams { - private readonly string? _value; + /// Argument string to pass to the command (empty string if none). + [JsonPropertyName("args")] + public string Args { get; set; } = string.Empty; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SessionLogLevel(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Name of the slash command to invoke (without the leading '/'). + [JsonPropertyName("commandName")] + public string CommandName { get; set; } = string.Empty; - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the info value. - public static SessionLogLevel Info { get; } = new("info"); +/// Indicates whether the command was accepted into the local execution queue. +public sealed class EnqueueCommandResult +{ + /// True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). + [JsonPropertyName("queued")] + public bool Queued { get; set; } +} - /// Gets the warning value. - public static SessionLogLevel Warning { get; } = new("warning"); +/// Slash-prefixed command string to enqueue for FIFO processing. +internal sealed class EnqueueCommandParams +{ + /// Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. + [JsonPropertyName("command")] + public string Command { get; set; } = string.Empty; - /// Gets the error value. - public static SessionLogLevel Error { get; } = new("error"); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionLogLevel left, SessionLogLevel right) => left.Equals(right); +/// Indicates whether the queued-command response was matched to a pending request. +public sealed class CommandsRespondToQueuedCommandResult +{ + /// Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionLogLevel left, SessionLogLevel right) => !(left == right); +/// Result of the queued command execution. +/// Data type discriminated by handled. +public partial class QueuedCommandResult +{ + /// The boolean discriminator. + [JsonPropertyName("handled")] + public bool Handled { get; set; } - /// - public override bool Equals(object? obj) => obj is SessionLogLevel other && Equals(other); + /// When true, the runtime will not process subsequent queued commands until a new request comes in. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("stopProcessingQueue")] + public bool? StopProcessingQueue { get; set; } +} - /// - public bool Equals(SessionLogLevel other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). +internal sealed class CommandsRespondToQueuedCommandRequest +{ + /// Request ID from the `command.queued` event the host is responding to. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Result of the queued command execution. + [JsonPropertyName("result")] + public QueuedCommandResult Result { get => field ??= new(); set; } - /// - public override string ToString() => Value; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SessionLogLevel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } +/// Feature override key/value pairs to attach to subsequent telemetry events from this session. +[Experimental(Diagnostics.Experimental)] +internal sealed class TelemetrySetFeatureOverridesRequest +{ + /// Override key/value pairs to attach to subsequent telemetry events from this session. Replaces any previously-set overrides. + [JsonPropertyName("features")] + public IDictionary Features { get => field ??= new Dictionary(); set; } - /// - public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } - -/// Authentication type. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct AuthInfoType : IEquatable +/// The elicitation response (accept with form values, decline, or cancel). +public sealed class UIElicitationResponse { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public AuthInfoType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). + [JsonPropertyName("action")] + public UIElicitationResponseAction Action { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// The form values submitted by the user (present when action is 'accept'). + [JsonPropertyName("content")] + public IDictionary? Content { get; set; } +} - /// Gets the hmac value. - public static AuthInfoType Hmac { get; } = new("hmac"); +/// JSON Schema describing the form fields to present to the user. +public sealed class UIElicitationSchema +{ + /// Form field definitions, keyed by field name. + [JsonPropertyName("properties")] + public IDictionary Properties { get => field ??= new Dictionary(); set; } - /// Gets the env value. - public static AuthInfoType Env { get; } = new("env"); + /// List of required field names. + [JsonPropertyName("required")] + public IList? Required { get; set; } - /// Gets the user value. - public static AuthInfoType User { get; } = new("user"); + /// Schema type indicator (always 'object'). + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; +} - /// Gets the gh-cli value. - public static AuthInfoType GhCli { get; } = new("gh-cli"); +/// Prompt message and JSON schema describing the form fields to elicit from the user. +internal sealed class UIElicitationRequest +{ + /// Message describing what information is needed from the user. + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; - /// Gets the api-key value. - public static AuthInfoType ApiKey { get; } = new("api-key"); + /// JSON Schema describing the form fields to present to the user. + [JsonPropertyName("requestedSchema")] + public UIElicitationSchema RequestedSchema { get => field ??= new(); set; } - /// Gets the token value. - public static AuthInfoType Token { get; } = new("token"); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the copilot-api-token value. - public static AuthInfoType CopilotApiToken { get; } = new("copilot-api-token"); +/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. +public sealed class UIElicitationResult +{ + /// Whether the response was accepted. False if the request was already resolved by another client. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(AuthInfoType left, AuthInfoType right) => left.Equals(right); +/// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). +internal sealed class UIHandlePendingElicitationRequest +{ + /// The unique request ID from the elicitation.requested event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(AuthInfoType left, AuthInfoType right) => !(left == right); + /// The elicitation response (accept with form values, decline, or cancel). + [JsonPropertyName("result")] + public UIElicitationResponse Result { get => field ??= new(); set; } - /// - public override bool Equals(object? obj) => obj is AuthInfoType other && Equals(other); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public bool Equals(AuthInfoType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Indicates whether the pending UI request was resolved by this call. +public sealed class UIHandlePendingResult +{ + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Schema for the `UIUserInputResponse` type. +public sealed class UIUserInputResponse +{ + /// The user's answer text. + [JsonPropertyName("answer")] + public string Answer { get; set; } = string.Empty; - /// - public override string ToString() => Value; + /// True if the user typed a freeform response, false if they selected a presented choice. Used by telemetry to differentiate between free text input and choice selection. + [JsonPropertyName("wasFreeform")] + public bool WasFreeform { get; set; } +} - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override AuthInfoType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } +/// Request ID of a pending `user_input.requested` event and the user's response. +internal sealed class UIHandlePendingUserInputRequest +{ + /// The unique request ID from the user_input.requested event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); - } - } + /// Schema for the `UIUserInputResponse` type. + [JsonPropertyName("response")] + public UIUserInputResponse Response { get => field ??= new(); set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. +public sealed class UIHandlePendingSamplingResponse +{ +} -/// Defines the allowed values. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct WorkspacesGetWorkspaceResultWorkspaceHostType : IEquatable +/// Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). +internal sealed class UIHandlePendingSamplingRequest { - private readonly string? _value; + /// The unique request ID from the sampling.requested event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public WorkspacesGetWorkspaceResultWorkspaceHostType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. + [JsonPropertyName("response")] + public UIHandlePendingSamplingResponse? Response { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the github value. - public static WorkspacesGetWorkspaceResultWorkspaceHostType Github { get; } = new("github"); +/// Request ID of a pending `auto_mode_switch.requested` event and the user's response. +internal sealed class UIHandlePendingAutoModeSwitchRequest +{ + /// The unique request ID from the auto_mode_switch.requested event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// Gets the ado value. - public static WorkspacesGetWorkspaceResultWorkspaceHostType Ado { get; } = new("ado"); + /// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). + [JsonPropertyName("response")] + public UIAutoModeSwitchResponse Response { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => left.Equals(right); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => !(left == right); +/// Schema for the `UIExitPlanModeResponse` type. +public sealed class UIExitPlanModeResponse +{ + /// Whether the plan was approved. + [JsonPropertyName("approved")] + public bool Approved { get; set; } - /// - public override bool Equals(object? obj) => obj is WorkspacesGetWorkspaceResultWorkspaceHostType other && Equals(other); + /// Whether subsequent edits should be auto-approved without confirmation. + [JsonPropertyName("autoApproveEdits")] + public bool? AutoApproveEdits { get; set; } - /// - public bool Equals(WorkspacesGetWorkspaceResultWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Feedback from the user when they declined the plan or requested changes. + [JsonPropertyName("feedback")] + public string? Feedback { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. + [JsonPropertyName("selectedAction")] + public UIExitPlanModeAction? SelectedAction { get; set; } +} - /// - public override string ToString() => Value; +/// Request ID of a pending `exit_plan_mode.requested` event and the user's response. +internal sealed class UIHandlePendingExitPlanModeRequest +{ + /// The unique request ID from the exit_plan_mode.requested event. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Schema for the `UIExitPlanModeResponse` type. + [JsonPropertyName("response")] + public UIExitPlanModeResponse Response { get => field ??= new(); set; } - /// - public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). +public sealed class UIRegisterDirectAutoModeSwitchHandlerResult +{ + /// Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. + [JsonPropertyName("handle")] + public string Handle { get; set; } = string.Empty; +} -/// Where this source lives — used for UI grouping. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct InstructionsSourcesLocation : IEquatable +/// Identifies the target session. +internal sealed class SessionUiRegisterDirectAutoModeSwitchHandlerRequest { - private readonly string? _value; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public InstructionsSourcesLocation(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } +/// Indicates whether the handle was active and the registration count was decremented. +public sealed class UIUnregisterDirectAutoModeSwitchHandlerResult +{ + /// True if the handle was active and decremented the counter; false if the handle was unknown. + [JsonPropertyName("unregistered")] + public bool Unregistered { get; set; } +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. +internal sealed class UIUnregisterDirectAutoModeSwitchHandlerRequest +{ + /// Handle previously returned by `registerDirectAutoModeSwitchHandler`. + [JsonPropertyName("handle")] + public string Handle { get; set; } = string.Empty; - /// Gets the user value. - public static InstructionsSourcesLocation User { get; } = new("user"); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the repository value. - public static InstructionsSourcesLocation Repository { get; } = new("repository"); +/// Indicates whether the operation succeeded. +public sealed class PermissionsConfigureResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Gets the working-directory value. - public static InstructionsSourcesLocation WorkingDirectory { get; } = new("working-directory"); +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. +public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRuleSource +{ + /// Gets or sets the name value. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(InstructionsSourcesLocation left, InstructionsSourcesLocation right) => left.Equals(right); + /// Gets or sets the type value. + [JsonPropertyName("type")] + public string Type { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(InstructionsSourcesLocation left, InstructionsSourcesLocation right) => !(left == right); +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. +public sealed class PermissionsConfigureAdditionalContentExclusionPolicyRule +{ + /// Gets or sets the ifAnyMatch value. + [JsonPropertyName("ifAnyMatch")] + public IList? IfAnyMatch { get; set; } - /// - public override bool Equals(object? obj) => obj is InstructionsSourcesLocation other && Equals(other); + /// Gets or sets the ifNoneMatch value. + [JsonPropertyName("ifNoneMatch")] + public IList? IfNoneMatch { get; set; } - /// - public bool Equals(InstructionsSourcesLocation other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Gets or sets the paths value. + [JsonPropertyName("paths")] + public IList Paths { get => field ??= []; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. + [JsonPropertyName("source")] + public PermissionsConfigureAdditionalContentExclusionPolicyRuleSource Source { get => field ??= new(); set; } +} - /// - public override string ToString() => Value; +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. +public sealed class PermissionsConfigureAdditionalContentExclusionPolicy +{ + /// Gets or sets the last_updated_at value. + [JsonPropertyName("last_updated_at")] + public object LastUpdatedAt { get; set; } = null!; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override InstructionsSourcesLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Gets or sets the rules value. + [JsonPropertyName("rules")] + public IList Rules { get => field ??= []; set; } - /// - public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); - } - } + /// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. + [JsonPropertyName("scope")] + public PermissionsConfigureAdditionalContentExclusionPolicyScope Scope { get; set; } } - -/// Category of instruction source — used for merge logic. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct InstructionsSourcesType : IEquatable +/// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. +public sealed class PermissionPathsConfig { - private readonly string? _value; + /// Additional directories to allow tool access to (in addition to the session's working directory). When `unrestricted` is true, these are still pre-populated on the UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention completion). + [JsonPropertyName("additionalDirectories")] + public IList? AdditionalDirectories { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public InstructionsSourcesType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Whether to include the system temp directory in the allowed list (defaults to true). Ignored when `unrestricted` is true. + [JsonPropertyName("includeTempDirectory")] + public bool? IncludeTempDirectory { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// If true, the runtime allows access to all paths without prompting. Equivalent to constructing an UnrestrictedPathManager. + [JsonPropertyName("unrestricted")] + public bool? Unrestricted { get; set; } - /// Gets the home value. - public static InstructionsSourcesType Home { get; } = new("home"); + /// Workspace root path (special-cased to be allowed even before the directory exists). Ignored when `unrestricted` is true. + [JsonPropertyName("workspacePath")] + public string? WorkspacePath { get; set; } +} - /// Gets the repo value. - public static InstructionsSourcesType Repo { get; } = new("repo"); - - /// Gets the model value. - public static InstructionsSourcesType Model { get; } = new("model"); - - /// Gets the vscode value. - public static InstructionsSourcesType Vscode { get; } = new("vscode"); +/// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. +public sealed class PermissionRulesSet +{ + /// Rules that auto-approve matching requests. + [JsonPropertyName("approved")] + public IList Approved { get => field ??= []; set; } - /// Gets the nested-agents value. - public static InstructionsSourcesType NestedAgents { get; } = new("nested-agents"); + /// Rules that auto-deny matching requests. + [JsonPropertyName("denied")] + public IList Denied { get => field ??= []; set; } +} - /// Gets the child-instructions value. - public static InstructionsSourcesType ChildInstructions { get; } = new("child-instructions"); +/// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. +public sealed class PermissionUrlsConfig +{ + /// Initial list of allowed URL/domain patterns. Patterns may include path components. Ignored when `unrestricted` is true. + [JsonPropertyName("initialAllowed")] + public IList? InitialAllowed { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(InstructionsSourcesType left, InstructionsSourcesType right) => left.Equals(right); + /// If true, the runtime allows access to all URLs without prompting. Initial allow-list is ignored when this is true. + [JsonPropertyName("unrestricted")] + public bool? Unrestricted { get; set; } +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(InstructionsSourcesType left, InstructionsSourcesType right) => !(left == right); +/// Patch of permission policy fields to apply (omit a field to leave it unchanged). +internal sealed class PermissionsConfigureParams +{ + /// If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. + [JsonPropertyName("additionalContentExclusionPolicies")] + public IList? AdditionalContentExclusionPolicies { get; set; } - /// - public override bool Equals(object? obj) => obj is InstructionsSourcesType other && Equals(other); + /// If specified, sets whether path/URL read permission requests are auto-approved. Omit to leave the current value unchanged. + [JsonPropertyName("approveAllReadPermissionRequests")] + public bool? ApproveAllReadPermissionRequests { get; set; } - /// - public bool Equals(InstructionsSourcesType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// If specified, sets whether tool permission requests are auto-approved without prompting. Omit to leave the current value unchanged. + [JsonPropertyName("approveAllToolPermissionRequests")] + public bool? ApproveAllToolPermissionRequests { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. + [JsonPropertyName("paths")] + public PermissionPathsConfig? Paths { get; set; } - /// - public override string ToString() => Value; + /// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. + [JsonPropertyName("rules")] + public PermissionRulesSet? Rules { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override InstructionsSourcesType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, InstructionsSourcesType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); - } - } + /// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. + [JsonPropertyName("urls")] + public PermissionUrlsConfig? Urls { get; set; } } - -/// Whether task execution is synchronously awaited or managed in the background. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct TaskExecutionMode : IEquatable +/// Indicates whether the permission decision was applied; false when the request was already resolved. +public sealed class PermissionRequestResult { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public TaskExecutionMode(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Whether the permission request was handled successfully. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// The client's response to the pending permission prompt. +/// Polymorphic base type discriminated by kind. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "kind", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(PermissionDecisionApproveOnce), "approve-once")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSession), "approve-for-session")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocation), "approve-for-location")] +[JsonDerivedType(typeof(PermissionDecisionApprovePermanently), "approve-permanently")] +[JsonDerivedType(typeof(PermissionDecisionReject), "reject")] +[JsonDerivedType(typeof(PermissionDecisionUserNotAvailable), "user-not-available")] +[JsonDerivedType(typeof(PermissionDecisionApproved), "approved")] +[JsonDerivedType(typeof(PermissionDecisionApprovedForSession), "approved-for-session")] +[JsonDerivedType(typeof(PermissionDecisionApprovedForLocation), "approved-for-location")] +[JsonDerivedType(typeof(PermissionDecisionCancelled), "cancelled")] +[JsonDerivedType(typeof(PermissionDecisionDeniedByRules), "denied-by-rules")] +[JsonDerivedType(typeof(PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser), "denied-no-approval-rule-and-could-not-request-from-user")] +[JsonDerivedType(typeof(PermissionDecisionDeniedInteractivelyByUser), "denied-interactively-by-user")] +[JsonDerivedType(typeof(PermissionDecisionDeniedByContentExclusionPolicy), "denied-by-content-exclusion-policy")] +[JsonDerivedType(typeof(PermissionDecisionDeniedByPermissionRequestHook), "denied-by-permission-request-hook")] +public partial class PermissionDecision +{ + /// The type discriminator. + [JsonPropertyName("kind")] + public virtual string Kind { get; set; } = string.Empty; +} - /// Gets the sync value. - public static TaskExecutionMode Sync { get; } = new("sync"); - /// Gets the background value. - public static TaskExecutionMode Background { get; } = new("background"); +/// Schema for the `PermissionDecisionApproveOnce` type. +/// The approve-once variant of . +public partial class PermissionDecisionApproveOnce : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "approve-once"; +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(TaskExecutionMode left, TaskExecutionMode right) => left.Equals(right); +/// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts). +/// Polymorphic base type discriminated by kind. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "kind", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalCommands), "commands")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalRead), "read")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalWrite), "write")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMcp), "mcp")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMcpSampling), "mcp-sampling")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalMemory), "memory")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalCustomTool), "custom-tool")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalExtensionManagement), "extension-management")] +[JsonDerivedType(typeof(PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess), "extension-permission-access")] +public partial class PermissionDecisionApproveForSessionApproval +{ + /// The type discriminator. + [JsonPropertyName("kind")] + public virtual string Kind { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(TaskExecutionMode left, TaskExecutionMode right) => !(left == right); +/// Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. +/// The commands variant of . +public partial class PermissionDecisionApproveForSessionApprovalCommands : PermissionDecisionApproveForSessionApproval +{ /// - public override bool Equals(object? obj) => obj is TaskExecutionMode other && Equals(other); + [JsonIgnore] + public override string Kind => "commands"; - /// - public bool Equals(TaskExecutionMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Command identifiers covered by this approval. + [JsonPropertyName("commandIdentifiers")] + public required IList CommandIdentifiers { get; set; } +} +/// Schema for the `PermissionDecisionApproveForSessionApprovalRead` type. +/// The read variant of . +public partial class PermissionDecisionApproveForSessionApprovalRead : PermissionDecisionApproveForSessionApproval +{ /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + [JsonIgnore] + public override string Kind => "read"; +} +/// Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type. +/// The write variant of . +public partial class PermissionDecisionApproveForSessionApprovalWrite : PermissionDecisionApproveForSessionApproval +{ /// - public override string ToString() => Value; - - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override TaskExecutionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } - - /// - public override void Write(Utf8JsonWriter writer, TaskExecutionMode value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); - } - } + [JsonIgnore] + public override string Kind => "write"; } - -/// Current lifecycle status of the task. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct TaskStatus : IEquatable +/// Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type. +/// The mcp variant of . +public partial class PermissionDecisionApproveForSessionApprovalMcp : PermissionDecisionApproveForSessionApproval { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public TaskStatus(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } - - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; - - /// Gets the running value. - public static TaskStatus Running { get; } = new("running"); - - /// Gets the idle value. - public static TaskStatus Idle { get; } = new("idle"); - - /// Gets the completed value. - public static TaskStatus Completed { get; } = new("completed"); + /// + [JsonIgnore] + public override string Kind => "mcp"; - /// Gets the failed value. - public static TaskStatus Failed { get; } = new("failed"); + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } - /// Gets the cancelled value. - public static TaskStatus Cancelled { get; } = new("cancelled"); + /// MCP tool name, or null to cover every tool on the server. + [JsonPropertyName("toolName")] + public string? ToolName { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(TaskStatus left, TaskStatus right) => left.Equals(right); +/// Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type. +/// The mcp-sampling variant of . +public partial class PermissionDecisionApproveForSessionApprovalMcpSampling : PermissionDecisionApproveForSessionApproval +{ + /// + [JsonIgnore] + public override string Kind => "mcp-sampling"; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(TaskStatus left, TaskStatus right) => !(left == right); + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } +} +/// Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type. +/// The memory variant of . +public partial class PermissionDecisionApproveForSessionApprovalMemory : PermissionDecisionApproveForSessionApproval +{ /// - public override bool Equals(object? obj) => obj is TaskStatus other && Equals(other); + [JsonIgnore] + public override string Kind => "memory"; +} +/// Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type. +/// The custom-tool variant of . +public partial class PermissionDecisionApproveForSessionApprovalCustomTool : PermissionDecisionApproveForSessionApproval +{ /// - public bool Equals(TaskStatus other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + [JsonIgnore] + public override string Kind => "custom-tool"; - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Custom tool name. + [JsonPropertyName("toolName")] + public required string ToolName { get; set; } +} +/// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type. +/// The extension-management variant of . +public partial class PermissionDecisionApproveForSessionApprovalExtensionManagement : PermissionDecisionApproveForSessionApproval +{ /// - public override string ToString() => Value; + [JsonIgnore] + public override string Kind => "extension-management"; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override TaskStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } - - /// - public override void Write(Utf8JsonWriter writer, TaskStatus value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); - } - } + /// Optional operation identifier; when omitted, the approval covers all extension management operations. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("operation")] + public string? Operation { get; set; } } - -/// Whether the shell runs inside a managed PTY session or as an independent background process. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct TaskShellInfoAttachmentMode : IEquatable +/// Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` type. +/// The extension-permission-access variant of . +public partial class PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess : PermissionDecisionApproveForSessionApproval { - private readonly string? _value; + /// + [JsonIgnore] + public override string Kind => "extension-permission-access"; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public TaskShellInfoAttachmentMode(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Extension name. + [JsonPropertyName("extensionName")] + public required string ExtensionName { get; set; } +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// Schema for the `PermissionDecisionApproveForSession` type. +/// The approve-for-session variant of . +public partial class PermissionDecisionApproveForSession : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "approve-for-session"; - /// Gets the attached value. - public static TaskShellInfoAttachmentMode Attached { get; } = new("attached"); + /// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("approval")] + public PermissionDecisionApproveForSessionApproval? Approval { get; set; } - /// Gets the detached value. - public static TaskShellInfoAttachmentMode Detached { get; } = new("detached"); + /// URL domain to approve for the rest of the session (URL prompts only). + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("domain")] + public string? Domain { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(TaskShellInfoAttachmentMode left, TaskShellInfoAttachmentMode right) => left.Equals(right); +/// Approval to persist for this location. +/// Polymorphic base type discriminated by kind. +[JsonPolymorphic( + TypeDiscriminatorPropertyName = "kind", + UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalCommands), "commands")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalRead), "read")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalWrite), "write")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMcp), "mcp")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMcpSampling), "mcp-sampling")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalMemory), "memory")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalCustomTool), "custom-tool")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalExtensionManagement), "extension-management")] +[JsonDerivedType(typeof(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess), "extension-permission-access")] +public partial class PermissionDecisionApproveForLocationApproval +{ + /// The type discriminator. + [JsonPropertyName("kind")] + public virtual string Kind { get; set; } = string.Empty; +} - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(TaskShellInfoAttachmentMode left, TaskShellInfoAttachmentMode right) => !(left == right); +/// Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. +/// The commands variant of . +public partial class PermissionDecisionApproveForLocationApprovalCommands : PermissionDecisionApproveForLocationApproval +{ /// - public override bool Equals(object? obj) => obj is TaskShellInfoAttachmentMode other && Equals(other); + [JsonIgnore] + public override string Kind => "commands"; + + /// Command identifiers covered by this approval. + [JsonPropertyName("commandIdentifiers")] + public required IList CommandIdentifiers { get; set; } +} +/// Schema for the `PermissionDecisionApproveForLocationApprovalRead` type. +/// The read variant of . +public partial class PermissionDecisionApproveForLocationApprovalRead : PermissionDecisionApproveForLocationApproval +{ /// - public bool Equals(TaskShellInfoAttachmentMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + [JsonIgnore] + public override string Kind => "read"; +} +/// Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type. +/// The write variant of . +public partial class PermissionDecisionApproveForLocationApprovalWrite : PermissionDecisionApproveForLocationApproval +{ /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + [JsonIgnore] + public override string Kind => "write"; +} +/// Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type. +/// The mcp variant of . +public partial class PermissionDecisionApproveForLocationApprovalMcp : PermissionDecisionApproveForLocationApproval +{ /// - public override string ToString() => Value; + [JsonIgnore] + public override string Kind => "mcp"; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override TaskShellInfoAttachmentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } - /// - public override void Write(Utf8JsonWriter writer, TaskShellInfoAttachmentMode value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); - } - } + /// MCP tool name, or null to cover every tool on the server. + [JsonPropertyName("toolName")] + public string? ToolName { get; set; } } - -/// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/). -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ExtensionSource : IEquatable +/// Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type. +/// The mcp-sampling variant of . +public partial class PermissionDecisionApproveForLocationApprovalMcpSampling : PermissionDecisionApproveForLocationApproval { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ExtensionSource(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } - - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// + [JsonIgnore] + public override string Kind => "mcp-sampling"; - /// Gets the project value. - public static ExtensionSource Project { get; } = new("project"); + /// MCP server name. + [JsonPropertyName("serverName")] + public required string ServerName { get; set; } +} - /// Gets the user value. - public static ExtensionSource User { get; } = new("user"); +/// Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type. +/// The memory variant of . +public partial class PermissionDecisionApproveForLocationApprovalMemory : PermissionDecisionApproveForLocationApproval +{ + /// + [JsonIgnore] + public override string Kind => "memory"; +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ExtensionSource left, ExtensionSource right) => left.Equals(right); +/// Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type. +/// The custom-tool variant of . +public partial class PermissionDecisionApproveForLocationApprovalCustomTool : PermissionDecisionApproveForLocationApproval +{ + /// + [JsonIgnore] + public override string Kind => "custom-tool"; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ExtensionSource left, ExtensionSource right) => !(left == right); + /// Custom tool name. + [JsonPropertyName("toolName")] + public required string ToolName { get; set; } +} +/// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type. +/// The extension-management variant of . +public partial class PermissionDecisionApproveForLocationApprovalExtensionManagement : PermissionDecisionApproveForLocationApproval +{ /// - public override bool Equals(object? obj) => obj is ExtensionSource other && Equals(other); + [JsonIgnore] + public override string Kind => "extension-management"; - /// - public bool Equals(ExtensionSource other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Optional operation identifier; when omitted, the approval covers all extension management operations. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("operation")] + public string? Operation { get; set; } +} +/// Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` type. +/// The extension-permission-access variant of . +public partial class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess : PermissionDecisionApproveForLocationApproval +{ /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + [JsonIgnore] + public override string Kind => "extension-permission-access"; + + /// Extension name. + [JsonPropertyName("extensionName")] + public required string ExtensionName { get; set; } +} +/// Schema for the `PermissionDecisionApproveForLocation` type. +/// The approve-for-location variant of . +public partial class PermissionDecisionApproveForLocation : PermissionDecision +{ /// - public override string ToString() => Value; + [JsonIgnore] + public override string Kind => "approve-for-location"; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Approval to persist for this location. + [JsonPropertyName("approval")] + public required PermissionDecisionApproveForLocationApproval Approval { get; set; } - /// - public override void Write(Utf8JsonWriter writer, ExtensionSource value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); - } - } + /// Location key (git root or cwd) to persist the approval to. + [JsonPropertyName("locationKey")] + public required string LocationKey { get; set; } } - -/// Current status: running, disabled, failed, or starting. -[Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ExtensionStatus : IEquatable +/// Schema for the `PermissionDecisionApprovePermanently` type. +/// The approve-permanently variant of . +public partial class PermissionDecisionApprovePermanently : PermissionDecision { - private readonly string? _value; - - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ExtensionStatus(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } - - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; - - /// Gets the running value. - public static ExtensionStatus Running { get; } = new("running"); - - /// Gets the disabled value. - public static ExtensionStatus Disabled { get; } = new("disabled"); - - /// Gets the failed value. - public static ExtensionStatus Failed { get; } = new("failed"); + /// + [JsonIgnore] + public override string Kind => "approve-permanently"; - /// Gets the starting value. - public static ExtensionStatus Starting { get; } = new("starting"); + /// URL domain to approve permanently. + [JsonPropertyName("domain")] + public required string Domain { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ExtensionStatus left, ExtensionStatus right) => left.Equals(right); +/// Schema for the `PermissionDecisionReject` type. +/// The reject variant of . +public partial class PermissionDecisionReject : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "reject"; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ExtensionStatus left, ExtensionStatus right) => !(left == right); + /// Optional feedback explaining the rejection. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("feedback")] + public string? Feedback { get; set; } +} +/// Schema for the `PermissionDecisionUserNotAvailable` type. +/// The user-not-available variant of . +public partial class PermissionDecisionUserNotAvailable : PermissionDecision +{ /// - public override bool Equals(object? obj) => obj is ExtensionStatus other && Equals(other); + [JsonIgnore] + public override string Kind => "user-not-available"; +} +/// Schema for the `PermissionDecisionApproved` type. +/// The approved variant of . +public partial class PermissionDecisionApproved : PermissionDecision +{ /// - public bool Equals(ExtensionStatus other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + [JsonIgnore] + public override string Kind => "approved"; +} +/// Schema for the `PermissionDecisionApprovedForSession` type. +/// The approved-for-session variant of . +public partial class PermissionDecisionApprovedForSession : PermissionDecision +{ /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + [JsonIgnore] + public override string Kind => "approved-for-session"; + /// The approval to add as a session-scoped rule. + [JsonPropertyName("approval")] + public required UserToolSessionApproval Approval { get; set; } +} + +/// Schema for the `PermissionDecisionApprovedForLocation` type. +/// The approved-for-location variant of . +public partial class PermissionDecisionApprovedForLocation : PermissionDecision +{ /// - public override string ToString() => Value; + [JsonIgnore] + public override string Kind => "approved-for-location"; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// The approval to persist for this location. + [JsonPropertyName("approval")] + public required UserToolSessionApproval Approval { get; set; } - /// - public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); - } - } + /// The location key (git root or cwd) to persist the approval to. + [JsonPropertyName("locationKey")] + public required string LocationKey { get; set; } } +/// Schema for the `PermissionDecisionCancelled` type. +/// The cancelled variant of . +public partial class PermissionDecisionCancelled : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "cancelled"; -/// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SlashCommandInputCompletion : IEquatable + /// Optional explanation of why the request was cancelled. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("reason")] + public string? Reason { get; set; } +} + +/// Schema for the `PermissionDecisionDeniedByRules` type. +/// The denied-by-rules variant of . +public partial class PermissionDecisionDeniedByRules : PermissionDecision { - private readonly string? _value; + /// + [JsonIgnore] + public override string Kind => "denied-by-rules"; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SlashCommandInputCompletion(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Rules that denied the request. + [JsonPropertyName("rules")] + public required IList Rules { get; set; } +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. +/// The denied-no-approval-rule-and-could-not-request-from-user variant of . +public partial class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "denied-no-approval-rule-and-could-not-request-from-user"; +} - /// Gets the directory value. - public static SlashCommandInputCompletion Directory { get; } = new("directory"); +/// Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. +/// The denied-interactively-by-user variant of . +public partial class PermissionDecisionDeniedInteractivelyByUser : PermissionDecision +{ + /// + [JsonIgnore] + public override string Kind => "denied-interactively-by-user"; - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SlashCommandInputCompletion left, SlashCommandInputCompletion right) => left.Equals(right); + /// Optional feedback from the user explaining the denial. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("feedback")] + public string? Feedback { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SlashCommandInputCompletion left, SlashCommandInputCompletion right) => !(left == right); + /// Whether to force-reject the current agent turn. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("forceReject")] + public bool? ForceReject { get; set; } +} +/// Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. +/// The denied-by-content-exclusion-policy variant of . +public partial class PermissionDecisionDeniedByContentExclusionPolicy : PermissionDecision +{ /// - public override bool Equals(object? obj) => obj is SlashCommandInputCompletion other && Equals(other); + [JsonIgnore] + public override string Kind => "denied-by-content-exclusion-policy"; - /// - public bool Equals(SlashCommandInputCompletion other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Human-readable explanation of why the path was excluded. + [JsonPropertyName("message")] + public required string Message { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// File path that triggered the exclusion. + [JsonPropertyName("path")] + public required string Path { get; set; } +} +/// Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. +/// The denied-by-permission-request-hook variant of . +public partial class PermissionDecisionDeniedByPermissionRequestHook : PermissionDecision +{ /// - public override string ToString() => Value; + [JsonIgnore] + public override string Kind => "denied-by-permission-request-hook"; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SlashCommandInputCompletion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Whether to interrupt the current agent turn. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("interrupt")] + public bool? Interrupt { get; set; } - /// - public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); - } - } + /// Optional message from the hook explaining the denial. + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [JsonPropertyName("message")] + public string? Message { get; set; } } +/// Pending permission request ID and the decision to apply (approve/reject and scope). +internal sealed class PermissionDecisionRequest +{ + /// Request ID of the pending permission request. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; -/// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SlashCommandKind : IEquatable + /// The client's response to the pending permission prompt. + [JsonPropertyName("result")] + public PermissionDecision Result { get => field ??= new(); set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Schema for the `PendingPermissionRequest` type. +public sealed class PendingPermissionRequest { - private readonly string? _value; + /// The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook). + [JsonPropertyName("request")] + public PermissionPromptRequest Request { get; set; } = null!; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SlashCommandKind(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Unique identifier for the pending permission request. + [JsonPropertyName("requestId")] + public string RequestId { get; set; } = string.Empty; +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// List of pending permission requests reconstructed from event history. +public sealed class PendingPermissionRequestList +{ + /// Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. + [JsonPropertyName("items")] + public IList Items { get => field ??= []; set; } +} - /// Gets the builtin value. - public static SlashCommandKind Builtin { get; } = new("builtin"); +/// No parameters; returns currently-pending permission requests for the session. +internal sealed class PermissionsPendingRequestsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the skill value. - public static SlashCommandKind Skill { get; } = new("skill"); +/// Indicates whether the operation succeeded. +public sealed class PermissionsSetApproveAllResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Gets the client value. - public static SlashCommandKind Client { get; } = new("client"); +/// Allow-all toggle for tool permission requests, with an optional telemetry source. +internal sealed class PermissionsSetApproveAllRequest +{ + /// Whether to auto-approve all tool permission requests. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SlashCommandKind left, SlashCommandKind right) => left.Equals(right); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SlashCommandKind left, SlashCommandKind right) => !(left == right); + /// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. + [JsonPropertyName("source")] + public PermissionsSetApproveAllSource? Source { get; set; } +} - /// - public override bool Equals(object? obj) => obj is SlashCommandKind other && Equals(other); +/// Indicates whether the operation succeeded. +public sealed class PermissionsModifyRulesResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// - public bool Equals(SlashCommandKind other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Scope and add/remove instructions for modifying session- or location-scoped permission rules. +internal sealed class PermissionsModifyRulesParams +{ + /// Rules to add to the scope. Applied before `remove`/`removeAll`. + [JsonPropertyName("add")] + public IList? Add { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Specific rules to remove from the scope. Ignored when `removeAll` is true. + [JsonPropertyName("remove")] + public IList? Remove { get; set; } - /// - public override string ToString() => Value; + /// When true, removes every rule currently in the scope (after any `add` is applied). Useful for clearing the location scope wholesale. + [JsonPropertyName("removeAll")] + public bool? RemoveAll { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SlashCommandKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. + [JsonPropertyName("scope")] + public PermissionsModifyRulesScope Scope { get; set; } - /// - public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } - -/// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct UIElicitationResponseAction : IEquatable +/// Indicates whether the operation succeeded. +public sealed class PermissionsSetRequiredResult { - private readonly string? _value; + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public UIElicitationResponseAction(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } +/// Toggles whether permission prompts should be bridged into session events for this client. +internal sealed class PermissionsSetRequiredRequest +{ + /// Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). + [JsonPropertyName("required")] + public bool Required { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the accept value. - public static UIElicitationResponseAction Accept { get; } = new("accept"); +/// Indicates whether the operation succeeded. +public sealed class PermissionsResetSessionApprovalsResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Gets the decline value. - public static UIElicitationResponseAction Decline { get; } = new("decline"); +/// No parameters; clears all session-scoped tool permission approvals. +internal sealed class PermissionsResetSessionApprovalsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the cancel value. - public static UIElicitationResponseAction Cancel { get; } = new("cancel"); +/// Indicates whether the operation succeeded. +public sealed class PermissionsNotifyPromptShownResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(UIElicitationResponseAction left, UIElicitationResponseAction right) => left.Equals(right); +/// Notification payload describing the permission prompt that the client just rendered. +internal sealed class PermissionPromptShownNotification +{ + /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). + [JsonPropertyName("message")] + public string Message { get; set; } = string.Empty; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(UIElicitationResponseAction left, UIElicitationResponseAction right) => !(left == right); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override bool Equals(object? obj) => obj is UIElicitationResponseAction other && Equals(other); +/// Snapshot of the session's allow-listed directories and primary working directory. +public sealed class PermissionPathsList +{ + /// All directories currently allowed for tool access on this session. + [JsonPropertyName("directories")] + public IList Directories { get => field ??= []; set; } - /// - public bool Equals(UIElicitationResponseAction other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// The primary working directory for this session. + [JsonPropertyName("primary")] + public string Primary { get; set; } = string.Empty; +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// No parameters; returns the session's allow-listed directories. +internal sealed class PermissionsPathsListRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override string ToString() => Value; +/// Indicates whether the operation succeeded. +public sealed class PermissionsPathsAddResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override UIElicitationResponseAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } +/// Directory path to add to the session's allowed directories. +internal sealed class PermissionPathsAddParams +{ + /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); - } - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Indicates whether the operation succeeded. +public sealed class PermissionsPathsUpdatePrimaryResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} -/// Signal to send (default: SIGTERM). -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct ShellKillSignal : IEquatable +/// Directory path to set as the session's new primary working directory. +internal sealed class PermissionPathsUpdatePrimaryParams { - private readonly string? _value; + /// Directory to set as the new primary working directory for the session's permission policy. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public ShellKillSignal(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// Indicates whether the supplied path is within the session's allowed directories. +public sealed class PermissionPathsAllowedCheckResult +{ + /// Whether the path is within the session's allowed directories. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } +} - /// Gets the SIGTERM value. - public static ShellKillSignal SIGTERM { get; } = new("SIGTERM"); +/// Path to evaluate against the session's allowed directories. +internal sealed class PermissionPathsAllowedCheckParams +{ + /// Path to check against the session's allowed directories. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; - /// Gets the SIGKILL value. - public static ShellKillSignal SIGKILL { get; } = new("SIGKILL"); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the SIGINT value. - public static ShellKillSignal SIGINT { get; } = new("SIGINT"); +/// Indicates whether the supplied path is within the session's workspace directory. +public sealed class PermissionPathsWorkspaceCheckResult +{ + /// Whether the path is within the session workspace directory. + [JsonPropertyName("allowed")] + public bool Allowed { get; set; } +} - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(ShellKillSignal left, ShellKillSignal right) => left.Equals(right); +/// Path to evaluate against the session's workspace (primary) directory. +internal sealed class PermissionPathsWorkspaceCheckParams +{ + /// Path to check against the session workspace directory. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(ShellKillSignal left, ShellKillSignal right) => !(left == right); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override bool Equals(object? obj) => obj is ShellKillSignal other && Equals(other); +/// Indicates whether the operation succeeded. +public sealed class PermissionsUrlsSetUnrestrictedModeResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} - /// - public bool Equals(ShellKillSignal other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); +/// Whether the URL-permission policy should run in unrestricted mode. +internal sealed class PermissionUrlsSetUnrestrictedModeParams +{ + /// Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override string ToString() => Value; +/// The repository the remote session targets. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataSnapshotRemoteMetadataRepository +{ + /// The branch the remote session is operating on. + [JsonPropertyName("branch")] + public string Branch { get; set; } = string.Empty; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override ShellKillSignal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// The GitHub repository name (without owner). + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; - /// - public override void Write(Utf8JsonWriter writer, ShellKillSignal value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); - } - } + /// The GitHub owner (user or organization) of the target repository. + [JsonPropertyName("owner")] + public string Owner { get; set; } = string.Empty; } - -/// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. +/// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. [Experimental(Diagnostics.Experimental)] -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct RemoteSessionMode : IEquatable +public sealed class MetadataSnapshotRemoteMetadata { - private readonly string? _value; + /// The pull request number the remote session is associated with, if any. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("pullRequestNumber")] + public long? PullRequestNumber { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public RemoteSessionMode(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// The repository the remote session targets. + [JsonPropertyName("repository")] + public MetadataSnapshotRemoteMetadataRepository Repository { get => field ??= new(); set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// The original resource identifier (task ID or PR node ID), preserved across event-replay reconstructions. Falls back to `sessionId` when absent. + [JsonPropertyName("resourceId")] + public string? ResourceId { get; set; } - /// Gets the off value. - public static RemoteSessionMode Off { get; } = new("off"); + /// Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` invocation. + [JsonPropertyName("taskType")] + public MetadataSnapshotRemoteMetadataTaskType? TaskType { get; set; } +} - /// Gets the export value. - public static RemoteSessionMode Export { get; } = new("export"); +/// Public-facing projection of workspace metadata for SDK / TUI consumers. +public sealed class SessionMetadataSnapshotWorkspace +{ + /// Branch checked out at session start, if any. + [JsonPropertyName("branch")] + public string? Branch { get; set; } - /// Gets the on value. - public static RemoteSessionMode On { get; } = new("on"); + /// ISO 8601 timestamp when the workspace was created. + [JsonPropertyName("created_at")] + public DateTimeOffset? CreatedAt { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(RemoteSessionMode left, RemoteSessionMode right) => left.Equals(right); + /// Current working directory at session start. + [JsonPropertyName("cwd")] + public string? Cwd { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(RemoteSessionMode left, RemoteSessionMode right) => !(left == right); + /// Resolved git root for cwd, if any. + [JsonPropertyName("git_root")] + public string? GitRoot { get; set; } - /// - public override bool Equals(object? obj) => obj is RemoteSessionMode other && Equals(other); - - /// - public bool Equals(RemoteSessionMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Repository host type, if known. + [JsonPropertyName("host_type")] + public SessionMetadataSnapshotWorkspaceHostType? HostType { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Workspace identifier (1:1 with sessionId). + [JsonPropertyName("id")] + public Guid Id { get; set; } - /// - public override string ToString() => Value; + /// Display name for the session, if set. + [JsonPropertyName("name")] + public string? Name { get; set; } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override RemoteSessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Repository identifier in 'owner/repo' or 'org/project/repo' format, if any. + [JsonPropertyName("repository")] + public string? Repository { get; set; } - /// - public override void Write(Utf8JsonWriter writer, RemoteSessionMode value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); - } - } + /// ISO 8601 timestamp when the workspace was last updated. + [JsonPropertyName("updated_at")] + public DateTimeOffset? UpdatedAt { get; set; } } - -/// Error classification. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SessionFsErrorCode : IEquatable +/// Point-in-time snapshot of slow-changing session identifier and state fields. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionMetadataSnapshot { - private readonly string? _value; + /// True when the session was detected to be in use by another process at construction time. Local consumers may surface a confirmation prompt before fully attaching. Always false for new sessions. + [JsonPropertyName("alreadyInUse")] + public bool AlreadyInUse { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SessionFsErrorCode(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot'). + [JsonPropertyName("currentMode")] + public MetadataSnapshotCurrentMode CurrentMode { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// User-provided name supplied at session construction (via `--name`), if any. Immutable after construction. + [JsonPropertyName("initialName")] + public string? InitialName { get; set; } - /// Gets the ENOENT value. - public static SessionFsErrorCode ENOENT { get; } = new("ENOENT"); + /// Whether this is a remote session (i.e., one whose runtime executes elsewhere and is steered through this process). + [JsonPropertyName("isRemote")] + public bool IsRemote { get; set; } - /// Gets the UNKNOWN value. - public static SessionFsErrorCode UNKNOWN { get; } = new("UNKNOWN"); + /// ISO 8601 timestamp of when the session's persisted state was last modified on disk. For new sessions, equals startTime. For resumed sessions, reflects the previous modification time at construction. + [JsonPropertyName("modifiedTime")] + public DateTimeOffset ModifiedTime { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionFsErrorCode left, SessionFsErrorCode right) => left.Equals(right); + /// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. + [JsonPropertyName("remoteMetadata")] + public MetadataSnapshotRemoteMetadata? RemoteMetadata { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionFsErrorCode left, SessionFsErrorCode right) => !(left == right); + /// Currently selected model identifier, if any. + [JsonPropertyName("selectedModel")] + public string? SelectedModel { get; set; } - /// - public override bool Equals(object? obj) => obj is SessionFsErrorCode other && Equals(other); + /// The unique identifier of the session. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; - /// - public bool Equals(SessionFsErrorCode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// ISO 8601 timestamp of when the session started. + [JsonPropertyName("startTime")] + public DateTimeOffset StartTime { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Short human-readable summary of the session, if known. Omitted when no summary has been generated. + [JsonPropertyName("summary")] + public string? Summary { get; set; } - /// - public override string ToString() => Value; + /// Absolute path to the session's current working directory. + [JsonPropertyName("workingDirectory")] + public string WorkingDirectory { get; set; } = string.Empty; - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SessionFsErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + /// Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). + [JsonPropertyName("workspace")] + public SessionMetadataSnapshotWorkspace? Workspace { get; set; } - /// - public override void Write(Utf8JsonWriter writer, SessionFsErrorCode value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); - } - } + /// Absolute path to the session's workspace directory on disk, or null if the session has no associated workspace. + [JsonPropertyName("workspacePath")] + public string? WorkspacePath { get; set; } } +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionMetadataSnapshotRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} -/// Entry type. -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SessionFsReaddirWithTypesEntryType : IEquatable +/// Indicates whether the local session is currently processing a turn or background continuation. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataIsProcessingResult { - private readonly string? _value; + /// Whether the session is currently processing user/agent messages. False for non-local sessions (which don't run a local agentic loop). Reflects an in-flight turn or background continuation. + [JsonPropertyName("processing")] + public bool Processing { get; set; } +} - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SessionFsReaddirWithTypesEntryType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionMetadataIsProcessingRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; +/// Token-usage breakdown for the session's current context window. +public sealed class MetadataContextInfoResultContextInfo +{ + /// Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("bufferTokens")] + public long BufferTokens { get; set; } - /// Gets the file value. - public static SessionFsReaddirWithTypesEntryType File { get; } = new("file"); + /// Token count at which background compaction starts (configurable percentage of promptTokenLimit). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("compactionThreshold")] + public long CompactionThreshold { get; set; } - /// Gets the directory value. - public static SessionFsReaddirWithTypesEntryType Directory { get; } = new("directory"); + /// Tokens consumed by user/assistant/tool messages. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("conversationTokens")] + public long ConversationTokens { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionFsReaddirWithTypesEntryType left, SessionFsReaddirWithTypesEntryType right) => left.Equals(right); + /// Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("limit")] + public long Limit { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionFsReaddirWithTypesEntryType left, SessionFsReaddirWithTypesEntryType right) => !(left == right); + /// The model used for token counting. + [JsonPropertyName("modelName")] + public string ModelName { get; set; } = string.Empty; - /// - public override bool Equals(object? obj) => obj is SessionFsReaddirWithTypesEntryType other && Equals(other); + /// Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("promptTokenLimit")] + public long PromptTokenLimit { get; set; } - /// - public bool Equals(SessionFsReaddirWithTypesEntryType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Tokens consumed by the system prompt. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("systemTokens")] + public long SystemTokens { get; set; } - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + /// Tokens consumed by tool definitions sent to the model (excludes deferred tools). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("toolDefinitionsTokens")] + public long ToolDefinitionsTokens { get; set; } - /// - public override string ToString() => Value; + /// Sum of system, conversation and tool-definition tokens. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("totalTokens")] + public long TotalTokens { get; set; } +} - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter - { - /// - public override SessionFsReaddirWithTypesEntryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } +/// Token breakdown for the session's current context window, or null if uninitialized. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataContextInfoResult +{ + /// Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). + [JsonPropertyName("contextInfo")] + public MetadataContextInfoResultContextInfo? ContextInfo { get; set; } +} - /// - public override void Write(Utf8JsonWriter writer, SessionFsReaddirWithTypesEntryType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); - } - } +/// Model identifier and token limits used to compute the context-info breakdown. +[Experimental(Diagnostics.Experimental)] +internal sealed class MetadataContextInfoRequest +{ + /// Maximum output tokens allowed by the target model. Pass 0 if unknown. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("outputTokenLimit")] + public long OutputTokenLimit { get; set; } + + /// Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("promptTokenLimit")] + public long PromptTokenLimit { get; set; } + + /// Model identifier used for tokenization. Omit to use the session default. Used both for token counting and to compute display values. + [JsonPropertyName("selectedModel")] + public string? SelectedModel { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; } +/// Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataRecordContextChangeResult +{ +} -/// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected). -[JsonConverter(typeof(Converter))] -[DebuggerDisplay("{Value,nq}")] -public readonly struct SessionFsSqliteQueryType : IEquatable +/// Updated working directory and git context. Emitted as the new payload of `session.context_changed`. +[Experimental(Diagnostics.Experimental)] +public sealed class SessionWorkingDirectoryContext { - private readonly string? _value; + /// Merge-base commit SHA (fork point from the remote default branch). + [JsonPropertyName("baseCommit")] + public string? BaseCommit { get; set; } - /// Initializes a new instance of the struct. - /// The value to associate with this . - [JsonConstructor] - public SessionFsSqliteQueryType(string value) - { - ArgumentException.ThrowIfNullOrWhiteSpace(value); - _value = value; - } + /// Current git branch name. + [JsonPropertyName("branch")] + public string? Branch { get; set; } - /// Gets the value associated with this . - public string Value => _value ?? string.Empty; + /// Current working directory path. + [JsonPropertyName("cwd")] + public string Cwd { get; set; } = string.Empty; - /// Gets the exec value. - public static SessionFsSqliteQueryType Exec { get; } = new("exec"); + /// Root directory of the git repository, resolved via git rev-parse. + [JsonPropertyName("gitRoot")] + public string? GitRoot { get; set; } - /// Gets the query value. - public static SessionFsSqliteQueryType Query { get; } = new("query"); + /// Head commit of the current git branch. + [JsonPropertyName("headCommit")] + public string? HeadCommit { get; set; } - /// Gets the run value. - public static SessionFsSqliteQueryType Run { get; } = new("run"); + /// Hosting platform type of the repository. + [JsonPropertyName("hostType")] + public SessionWorkingDirectoryContextHostType? HostType { get; set; } - /// Returns a value indicating whether two instances are equivalent. - public static bool operator ==(SessionFsSqliteQueryType left, SessionFsSqliteQueryType right) => left.Equals(right); + /// Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps). + [JsonPropertyName("repository")] + public string? Repository { get; set; } - /// Returns a value indicating whether two instances are not equivalent. - public static bool operator !=(SessionFsSqliteQueryType left, SessionFsSqliteQueryType right) => !(left == right); + /// Raw host string from the git remote URL (e.g. "github.com", "dev.azure.com"). + [JsonPropertyName("repositoryHost")] + public string? RepositoryHost { get; set; } +} - /// - public override bool Equals(object? obj) => obj is SessionFsSqliteQueryType other && Equals(other); +/// Updated working-directory/git context to record on the session. +[Experimental(Diagnostics.Experimental)] +internal sealed class MetadataRecordContextChangeRequest +{ + /// Updated working directory and git context. Emitted as the new payload of `session.context_changed`. + [JsonPropertyName("context")] + public SessionWorkingDirectoryContext Context { get => field ??= new(); set; } - /// - public bool Equals(SessionFsSqliteQueryType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} - /// - public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); +/// Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataSetWorkingDirectoryResult +{ + /// Working directory after the update. + [JsonPropertyName("workingDirectory")] + public string WorkingDirectory { get; set; } = string.Empty; +} + +/// Absolute path to set as the session's new working directory. +[Experimental(Diagnostics.Experimental)] +internal sealed class MetadataSetWorkingDirectoryRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Absolute path to set as the session's working directory. The runtime updates the session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) anchor to it. + [JsonPropertyName("workingDirectory")] + public string WorkingDirectory { get; set; } = string.Empty; +} + +/// Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataRecomputeContextTokensResult +{ + /// Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("messagesTokenCount")] + public long MessagesTokenCount { get; set; } + + /// Tokens contributed by system/developer prompt snapshots. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("systemTokenCount")] + public long SystemTokenCount { get; set; } + + /// Sum of tokens across chat-context and system-context messages currently held by the session. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("totalTokens")] + public long TotalTokens { get; set; } +} + +/// Model identifier to use when re-tokenizing the session's existing messages. +[Experimental(Diagnostics.Experimental)] +internal sealed class MetadataRecomputeContextTokensRequest +{ + /// Model identifier used for tokenization. The runtime token-counts both chat-context and system-context messages against this model. + [JsonPropertyName("modelId")] + public string ModelId { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Identifier of the spawned process, used to correlate streamed output and exit notifications. +public sealed class ShellExecResult +{ + /// Unique identifier for tracking streamed output. + [JsonPropertyName("processId")] + public string ProcessId { get; set; } = string.Empty; +} + +/// Shell command to run, with optional working directory and timeout in milliseconds. +internal sealed class ShellExecRequest +{ + /// Shell command to execute. + [JsonPropertyName("command")] + public string Command { get; set; } = string.Empty; + + /// Working directory (defaults to session working directory). + [JsonPropertyName("cwd")] + public string? Cwd { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Timeout in milliseconds (default: 30000). + [Range((double)0, (double)long.MaxValue)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] + [JsonPropertyName("timeout")] + public TimeSpan? Timeout { get; set; } +} + +/// Indicates whether the signal was delivered; false if the process was unknown or already exited. +public sealed class ShellKillResult +{ + /// Whether the signal was sent successfully. + [JsonPropertyName("killed")] + public bool Killed { get; set; } +} + +/// Identifier of a process previously returned by "shell.exec" and the signal to send. +internal sealed class ShellKillRequest +{ + /// Process identifier returned by shell.exec. + [JsonPropertyName("processId")] + public string ProcessId { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Signal to send (default: SIGTERM). + [JsonPropertyName("signal")] + public ShellKillSignal? Signal { get; set; } +} + +/// Post-compaction context window usage breakdown. +[Experimental(Diagnostics.Experimental)] +public sealed class HistoryCompactContextWindow +{ + /// Token count from non-system messages (user, assistant, tool). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("conversationTokens")] + public long? ConversationTokens { get; set; } + + /// Current total tokens in the context window (system + conversation + tool definitions). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("currentTokens")] + public long CurrentTokens { get; set; } + + /// Current number of messages in the conversation. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("messagesLength")] + public long MessagesLength { get; set; } + + /// Token count from system message(s). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("systemTokens")] + public long? SystemTokens { get; set; } + + /// Maximum token count for the model's context window. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("tokenLimit")] + public long TokenLimit { get; set; } + + /// Token count from tool definitions. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("toolDefinitionsTokens")] + public long? ToolDefinitionsTokens { get; set; } +} + +/// Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. +[Experimental(Diagnostics.Experimental)] +public sealed class HistoryCompactResult +{ + /// Post-compaction context window usage breakdown. + [JsonPropertyName("contextWindow")] + public HistoryCompactContextWindow? ContextWindow { get; set; } + + /// Number of messages removed during compaction. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("messagesRemoved")] + public long MessagesRemoved { get; set; } + + /// Whether compaction completed successfully. + [JsonPropertyName("success")] + public bool Success { get; set; } + + /// Summary text produced by compaction. Omitted when compaction did not produce a summary (e.g. failure path). + [JsonPropertyName("summaryContent")] + public string? SummaryContent { get; set; } + + /// Number of tokens freed by compaction. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("tokensRemoved")] + public long TokensRemoved { get; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionHistoryCompactRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Number of events that were removed by the truncation. +[Experimental(Diagnostics.Experimental)] +public sealed class HistoryTruncateResult +{ + /// Number of events that were removed. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("eventsRemoved")] + public long EventsRemoved { get; set; } +} + +/// Identifier of the event to truncate to; this event and all later events are removed. +[Experimental(Diagnostics.Experimental)] +internal sealed class HistoryTruncateRequest +{ + /// Event ID to truncate to. This event and all events after it are removed from the session. + [JsonPropertyName("eventId")] + public string EventId { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether an in-progress background compaction was cancelled. +[Experimental(Diagnostics.Experimental)] +public sealed class HistoryCancelBackgroundCompactionResult +{ + /// Whether an in-progress background compaction was cancelled. False when no compaction was running, when the session is remote, or when the underlying processor was unavailable. + [JsonPropertyName("cancelled")] + public bool Cancelled { get; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionHistoryCancelBackgroundCompactionRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether an in-progress manual compaction was aborted. +[Experimental(Diagnostics.Experimental)] +public sealed class HistoryAbortManualCompactionResult +{ + /// Whether an in-progress manual compaction was aborted. False when no manual compaction was running, when its abort controller was already aborted, or when the session is remote. + [JsonPropertyName("aborted")] + public bool Aborted { get; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionHistoryAbortManualCompactionRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Markdown summary of the conversation context (empty when not available). +[Experimental(Diagnostics.Experimental)] +public sealed class HistorySummarizeForHandoffResult +{ + /// Markdown summary of the conversation context produced by an LLM. Empty string when there are no messages or when the session does not support local summarization. + [JsonPropertyName("summary")] + public string Summary { get; set; } = string.Empty; +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionHistorySummarizeForHandoffRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Schema for the `QueuePendingItems` type. +[Experimental(Diagnostics.Experimental)] +public sealed class QueuePendingItems +{ + /// Human-readable text to display for this queue entry in the UI. + [JsonPropertyName("displayText")] + public string DisplayText { get; set; } = string.Empty; + + /// Whether this item is a queued user message or a queued slash command / model change. + [JsonPropertyName("kind")] + public QueuePendingItemsKind Kind { get; set; } +} + +/// Snapshot of the session's pending queued items and immediate-steering messages. +[Experimental(Diagnostics.Experimental)] +public sealed class QueuePendingItemsResult +{ + /// Pending queued items in submission order. Includes user messages, queued slash commands, and queued model changes; omits internal system items. + [JsonPropertyName("items")] + public IList Items { get => field ??= []; set; } + + /// Display text for messages currently in the immediate steering queue (interjections sent during a running turn). + [JsonPropertyName("steeringMessages")] + public IList SteeringMessages { get => field ??= []; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionQueuePendingItemsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether a user-facing pending item was removed. +[Experimental(Diagnostics.Experimental)] +public sealed class QueueRemoveMostRecentResult +{ + /// True if a user-facing pending item was removed (LIFO across both queues); false when no removable items remained. + [JsonPropertyName("removed")] + public bool Removed { get; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionQueueRemoveMostRecentRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionQueueClearRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Batch of session events returned by a read, with cursor and continuation metadata. +[Experimental(Diagnostics.Experimental)] +public sealed class EventsReadResult +{ + /// Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue from where this read left off. Always present, even when no events were returned. + [JsonPropertyName("cursor")] + public string Cursor { get; set; } = string.Empty; + + /// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. + [JsonPropertyName("cursorStatus")] + public EventsCursorStatus CursorStatus { get; set; } + + /// Events are delivered in two batches per read: persisted events first (in append order), then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral events do not interleave within a single read. + [JsonPropertyName("events")] + public IList Events { get => field ??= []; set; } + + /// True when the read returned `max` events and more events are available immediately. When false, the next read with a non-zero `waitMs` will block until a new event arrives or the wait expires. + [JsonPropertyName("hasMore")] + public bool HasMore { get; set; } +} + +/// Cursor, batch size, and optional long-poll/filter parameters for reading session events. +[Experimental(Diagnostics.Experimental)] +internal sealed class EventLogReadRequest +{ + /// Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. + [JsonPropertyName("agentScope")] + public EventsAgentScope? AgentScope { get; set; } + + /// Opaque cursor returned by a previous read. Omit on the first call to start from the beginning of the session's persisted history. + [JsonPropertyName("cursor")] + public string? Cursor { get; set; } + + /// Maximum number of events to return in this batch (1–1000, default 200). + [Range((double)0, (double)1000, MinimumIsExclusive = true)] + [JsonPropertyName("max")] + public int? Max { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Either '*' to receive all event types, or a non-empty list of event types to receive. + [JsonPropertyName("types")] + public object? Types { get; set; } + + /// Milliseconds to wait for new events when the cursor is at the tail of history. 0 (default) returns immediately even if no events are available. Capped at 30000ms. Ephemeral events that arrive during the wait are delivered in this batch but are NOT replayable on a subsequent read (use a non-zero waitMs in your next call to capture future ephemerals as they happen). + [Range((double)0, (double)30000)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] + [JsonPropertyName("waitMs")] + public TimeSpan? Wait { get; set; } +} + +/// Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). +[Experimental(Diagnostics.Experimental)] +public sealed class EventLogTailResult +{ + /// Opaque cursor pointing at the current tail of the session's persisted-events history. Pass back to `read` to receive only events that arrive AFTER this snapshot. When the session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent to omitting the cursor on a first read). + [JsonPropertyName("cursor")] + public string Cursor { get; set; } = string.Empty; +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionEventLogTailRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Opaque handle representing an event-type interest registration. +[Experimental(Diagnostics.Experimental)] +public sealed class RegisterEventInterestResult +{ + /// Opaque handle for this registration. Pass to releaseInterest to release. Each call to registerInterest produces a fresh handle, even when the same eventType is registered multiple times. + [JsonPropertyName("handle")] + public string Handle { get; set; } = string.Empty; +} + +/// Event type to register consumer interest for, used by runtime gating logic. +[Experimental(Diagnostics.Experimental)] +internal sealed class RegisterEventInterestParams +{ + /// The event type the consumer wants the runtime to treat as 'observed' for behavior-switching gating. Some runtime code paths inspect whether any consumer is interested in a specific event type and choose a different implementation accordingly (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full interactive OAuth flow to the consumer; when no interest is registered the runtime installs a browserless fallback that silently reuses cached tokens). SDK clients that long-poll events do NOT automatically appear as listeners to these gating checks — they must explicitly call `registerInterest` for each event type they want the runtime to count as having a consumer. Multiple registrations for the same event type from the same or different consumers are tracked independently and must each be released. See: `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, `user_input.requested`, `elicitation.requested`, `command.queued`, `exit_plan_mode.requested`. + [JsonPropertyName("eventType")] + public string EventType { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the operation succeeded. +[Experimental(Diagnostics.Experimental)] +public sealed class EventLogReleaseInterestResult +{ + /// Whether the operation succeeded. + [JsonPropertyName("success")] + public bool Success { get; set; } +} + +/// Opaque handle previously returned by `registerInterest` to release. +[Experimental(Diagnostics.Experimental)] +internal sealed class ReleaseEventInterestParams +{ + /// Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown or already-released handle is a no-op (returns success). When the last outstanding handle for an event type is released, the runtime reverts to its 'no consumer' code path for that event type. + [JsonPropertyName("handle")] + public string Handle { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Aggregated code change metrics. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsCodeChanges +{ + /// Distinct file paths modified during the session. + [JsonPropertyName("filesModified")] + public IList FilesModified { get => field ??= []; set; } + + /// Number of distinct files modified. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("filesModifiedCount")] + public long FilesModifiedCount { get; set; } + + /// Total lines of code added. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("linesAdded")] + public long LinesAdded { get; set; } + + /// Total lines of code removed. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("linesRemoved")] + public long LinesRemoved { get; set; } +} + +/// Request count and cost metrics for this model. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsModelMetricRequests +{ + /// User-initiated premium request cost (with multiplier applied). + [JsonPropertyName("cost")] + public double Cost { get; set; } + + /// Number of API requests made with this model. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("count")] + public long Count { get; set; } +} + +/// Schema for the `UsageMetricsModelMetricTokenDetail` type. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsModelMetricTokenDetail +{ + /// Accumulated token count for this token type. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("tokenCount")] + public long TokenCount { get; set; } +} + +/// Token usage metrics for this model. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsModelMetricUsage +{ + /// Total tokens read from prompt cache. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("cacheReadTokens")] + public long CacheReadTokens { get; set; } + + /// Total tokens written to prompt cache. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("cacheWriteTokens")] + public long CacheWriteTokens { get; set; } + + /// Total input tokens consumed. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("inputTokens")] + public long InputTokens { get; set; } + + /// Total output tokens produced. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("outputTokens")] + public long OutputTokens { get; set; } + + /// Total output tokens used for reasoning. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("reasoningTokens")] + public long? ReasoningTokens { get; set; } +} + +/// Schema for the `UsageMetricsModelMetric` type. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsModelMetric +{ + /// Request count and cost metrics for this model. + [JsonPropertyName("requests")] + public UsageMetricsModelMetricRequests Requests { get => field ??= new(); set; } + + /// Token count details per type. + [JsonPropertyName("tokenDetails")] + public IDictionary? TokenDetails { get; set; } + + /// Accumulated nano-AI units cost for this model. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("totalNanoAiu")] + public long? TotalNanoAiu { get; set; } + + /// Token usage metrics for this model. + [JsonPropertyName("usage")] + public UsageMetricsModelMetricUsage Usage { get => field ??= new(); set; } +} + +/// Schema for the `UsageMetricsTokenDetail` type. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageMetricsTokenDetail +{ + /// Accumulated token count for this token type. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("tokenCount")] + public long TokenCount { get; set; } +} + +/// Accumulated session usage metrics, including premium request cost, token counts, model breakdown, and code-change totals. +[Experimental(Diagnostics.Experimental)] +public sealed class UsageGetMetricsResult +{ + /// Aggregated code change metrics. + [JsonPropertyName("codeChanges")] + public UsageMetricsCodeChanges CodeChanges { get => field ??= new(); set; } + + /// Currently active model identifier. + [JsonPropertyName("currentModel")] + public string? CurrentModel { get; set; } + + /// Input tokens from the most recent main-agent API call. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("lastCallInputTokens")] + public long LastCallInputTokens { get; set; } + + /// Output tokens from the most recent main-agent API call. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("lastCallOutputTokens")] + public long LastCallOutputTokens { get; set; } + + /// Per-model token and request metrics, keyed by model identifier. + [JsonPropertyName("modelMetrics")] + public IDictionary ModelMetrics { get => field ??= new Dictionary(); set; } + + /// ISO 8601 timestamp when the session started. + [JsonPropertyName("sessionStartTime")] + public DateTimeOffset SessionStartTime { get; set; } + + /// Session-wide per-token-type accumulated token counts. + [JsonPropertyName("tokenDetails")] + public IDictionary? TokenDetails { get; set; } + + /// Total time spent in model API calls (milliseconds). + [Range((double)0, (double)long.MaxValue)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] + [JsonPropertyName("totalApiDurationMs")] + public TimeSpan TotalApiDuration { get; set; } + + /// Session-wide accumulated nano-AI units cost. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("totalNanoAiu")] + public long? TotalNanoAiu { get; set; } + + /// Total user-initiated premium request cost across all models (may be fractional due to multipliers). + [JsonPropertyName("totalPremiumRequestCost")] + public double TotalPremiumRequestCost { get; set; } + + /// Raw count of user-initiated API requests. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("totalUserRequests")] + public long TotalUserRequests { get; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionUsageGetMetricsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// GitHub URL for the session and a flag indicating whether remote steering is enabled. +[Experimental(Diagnostics.Experimental)] +public sealed class RemoteEnableResult +{ + /// Whether remote steering is enabled. + [JsonPropertyName("remoteSteerable")] + public bool RemoteSteerable { get; set; } + + /// GitHub frontend URL for this session. + [Url] + [StringSyntax(StringSyntaxAttribute.Uri)] + [JsonPropertyName("url")] + public string? Url { get; set; } +} + +/// Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. +[Experimental(Diagnostics.Experimental)] +internal sealed class RemoteEnableRequest +{ + /// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. + [JsonPropertyName("mode")] + public RemoteSessionMode? Mode { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionRemoteDisableRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. +[Experimental(Diagnostics.Experimental)] +public sealed class RemoteNotifySteerableChangedResult +{ +} + +/// New remote-steerability state to persist as a `session.remote_steerable_changed` event. +[Experimental(Diagnostics.Experimental)] +internal sealed class RemoteNotifySteerableChangedRequest +{ + /// Whether the session now supports remote steering via GitHub. The runtime persists this as a `session.remote_steerable_changed` event so resume/replay sees the up-to-date capability. + [JsonPropertyName("remoteSteerable")] + public bool RemoteSteerable { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Schema for the `ScheduleEntry` type. +[Experimental(Diagnostics.Experimental)] +public sealed class ScheduleEntry +{ + /// Display-only label for the prompt as shown in the UI (e.g. `/skill-name` for a skill-invocation schedule). The actual enqueued prompt is `prompt`. + [JsonPropertyName("displayPrompt")] + public string? DisplayPrompt { get; set; } + + /// Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt from the event log). + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("id")] + public long Id { get; set; } + + /// Interval between scheduled ticks, in milliseconds. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] + [JsonPropertyName("intervalMs")] + public TimeSpan Interval { get; set; } + + /// ISO 8601 timestamp when the next tick is scheduled to fire. + [JsonPropertyName("nextRunAt")] + public DateTimeOffset NextRunAt { get; set; } + + /// Prompt text that gets enqueued on every tick. + [JsonPropertyName("prompt")] + public string Prompt { get; set; } = string.Empty; + + /// Whether the schedule re-arms after each tick (`/every`) or fires once (`/after`). + [JsonPropertyName("recurring")] + public bool Recurring { get; set; } +} + +/// Snapshot of the currently active recurring prompts for this session. +[Experimental(Diagnostics.Experimental)] +public sealed class ScheduleList +{ + /// Active scheduled prompts, ordered by id. + [JsonPropertyName("entries")] + public IList Entries { get => field ??= []; set; } +} + +/// Identifies the target session. +[Experimental(Diagnostics.Experimental)] +internal sealed class SessionScheduleListRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. +[Experimental(Diagnostics.Experimental)] +public sealed class ScheduleStopResult +{ + /// The removed entry, or omitted if no entry matched. + [JsonPropertyName("entry")] + public ScheduleEntry? Entry { get; set; } +} + +/// Identifier of the scheduled prompt to remove. +[Experimental(Diagnostics.Experimental)] +internal sealed class ScheduleStopRequest +{ + /// Id of the scheduled prompt to remove. + [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] + [JsonPropertyName("id")] + public long Id { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Describes a filesystem error. +public sealed class SessionFsError +{ + /// Error classification. + [JsonPropertyName("code")] + public SessionFsErrorCode Code { get; set; } + + /// Free-form detail about the error, for logging/diagnostics. + [JsonPropertyName("message")] + public string? Message { get; set; } +} + +/// File content as a UTF-8 string, or a filesystem error if the read failed. +public sealed class SessionFsReadFileResult +{ + /// File content as UTF-8 string. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; + + /// Describes a filesystem error. + [JsonPropertyName("error")] + public SessionFsError? Error { get; set; } +} + +/// Path of the file to read from the client-provided session filesystem. +public sealed class SessionFsReadFileRequest +{ + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// File path, content to write, and optional mode for the client-provided session filesystem. +public sealed class SessionFsWriteFileRequest +{ + /// Content to write. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; + + /// Optional POSIX-style mode for newly created files. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("mode")] + public long? Mode { get; set; } + + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// File path, content to append, and optional mode for the client-provided session filesystem. +public sealed class SessionFsAppendFileRequest +{ + /// Content to append. + [JsonPropertyName("content")] + public string Content { get; set; } = string.Empty; + + /// Optional POSIX-style mode for newly created files. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("mode")] + public long? Mode { get; set; } + + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the requested path exists in the client-provided session filesystem. +public sealed class SessionFsExistsResult +{ + /// Whether the path exists. + [JsonPropertyName("exists")] + public bool Exists { get; set; } +} + +/// Path to test for existence in the client-provided session filesystem. +public sealed class SessionFsExistsRequest +{ + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Filesystem metadata for the requested path, or a filesystem error if the stat failed. +public sealed class SessionFsStatResult +{ + /// ISO 8601 timestamp of creation. + [JsonPropertyName("birthtime")] + public DateTimeOffset Birthtime { get; set; } + + /// Describes a filesystem error. + [JsonPropertyName("error")] + public SessionFsError? Error { get; set; } + + /// Whether the path is a directory. + [JsonPropertyName("isDirectory")] + public bool IsDirectory { get; set; } + + /// Whether the path is a file. + [JsonPropertyName("isFile")] + public bool IsFile { get; set; } + + /// ISO 8601 timestamp of last modification. + [JsonPropertyName("mtime")] + public DateTimeOffset Mtime { get; set; } + + /// File size in bytes. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("size")] + public long Size { get; set; } +} + +/// Path whose metadata should be returned from the client-provided session filesystem. +public sealed class SessionFsStatRequest +{ + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. +public sealed class SessionFsMkdirRequest +{ + /// Optional POSIX-style mode for newly created directories. + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("mode")] + public long? Mode { get; set; } + + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Create parent directories as needed. + [JsonPropertyName("recursive")] + public bool? Recursive { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Names of entries in the requested directory, or a filesystem error if the read failed. +public sealed class SessionFsReaddirResult +{ + /// Entry names in the directory. + [JsonPropertyName("entries")] + public IList Entries { get => field ??= []; set; } + + /// Describes a filesystem error. + [JsonPropertyName("error")] + public SessionFsError? Error { get; set; } +} + +/// Directory path whose entries should be listed from the client-provided session filesystem. +public sealed class SessionFsReaddirRequest +{ + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Schema for the `SessionFsReaddirWithTypesEntry` type. +public sealed class SessionFsReaddirWithTypesEntry +{ + /// Entry name. + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + /// Entry type. + [JsonPropertyName("type")] + public SessionFsReaddirWithTypesEntryType Type { get; set; } +} + +/// Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. +public sealed class SessionFsReaddirWithTypesResult +{ + /// Directory entries with type information. + [JsonPropertyName("entries")] + public IList Entries { get => field ??= []; set; } + + /// Describes a filesystem error. + [JsonPropertyName("error")] + public SessionFsError? Error { get; set; } +} + +/// Directory path whose entries (with type information) should be listed from the client-provided session filesystem. +public sealed class SessionFsReaddirWithTypesRequest +{ + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Path to remove from the client-provided session filesystem, with options for recursive removal and force. +public sealed class SessionFsRmRequest +{ + /// Ignore errors if the path does not exist. + [JsonPropertyName("force")] + public bool? Force { get; set; } + + /// Path using SessionFs conventions. + [JsonPropertyName("path")] + public string Path { get; set; } = string.Empty; + + /// Remove directories and their contents recursively. + [JsonPropertyName("recursive")] + public bool? Recursive { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Source and destination paths for renaming or moving an entry in the client-provided session filesystem. +public sealed class SessionFsRenameRequest +{ + /// Destination path using SessionFs conventions. + [JsonPropertyName("dest")] + public string Dest { get; set; } = string.Empty; + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; + + /// Source path using SessionFs conventions. + [JsonPropertyName("src")] + public string Src { get; set; } = string.Empty; +} + +/// Query results including rows, columns, and rows affected, or a filesystem error if execution failed. +public sealed class SessionFsSqliteQueryResult +{ + /// Column names from the result set. + [JsonPropertyName("columns")] + public IList Columns { get => field ??= []; set; } + + /// Describes a filesystem error. + [JsonPropertyName("error")] + public SessionFsError? Error { get; set; } + + /// SQLite last_insert_rowid() value for INSERT. + [JsonPropertyName("lastInsertRowid")] + public long? LastInsertRowid { get; set; } + + /// For SELECT: array of row objects. For others: empty array. + [JsonPropertyName("rows")] + public IList> Rows { get => field ??= []; set; } + + /// Number of rows affected (for INSERT/UPDATE/DELETE). + [Range((double)0, (double)long.MaxValue)] + [JsonPropertyName("rowsAffected")] + public long RowsAffected { get; set; } +} + +/// SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. +public sealed class SessionFsSqliteQueryRequest +{ + /// Optional named bind parameters. + [JsonPropertyName("params")] + public IDictionary? Params { get; set; } + + /// SQL query to execute. + [JsonPropertyName("query")] + public string Query { get; set; } = string.Empty; + + /// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected). + [JsonPropertyName("queryType")] + public SessionFsSqliteQueryType QueryType { get; set; } + + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Indicates whether the per-session SQLite database already exists. +public sealed class SessionFsSqliteExistsResult +{ + /// Whether the session database already exists. + [JsonPropertyName("exists")] + public bool Exists { get; set; } +} + +/// Identifies the target session. +public sealed class SessionFsSqliteExistsRequest +{ + /// Target session identifier. + [JsonPropertyName("sessionId")] + public string SessionId { get; set; } = string.Empty; +} + +/// Model capability category for grouping in the model picker. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ModelPickerCategory : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ModelPickerCategory(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the lightweight value. + public static ModelPickerCategory Lightweight { get; } = new("lightweight"); + + /// Gets the versatile value. + public static ModelPickerCategory Versatile { get; } = new("versatile"); + + /// Gets the powerful value. + public static ModelPickerCategory Powerful { get; } = new("powerful"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ModelPickerCategory left, ModelPickerCategory right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ModelPickerCategory left, ModelPickerCategory right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ModelPickerCategory other && Equals(other); + + /// + public bool Equals(ModelPickerCategory other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ModelPickerCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ModelPickerCategory value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerCategory)); + } + } +} + + +/// Relative cost tier for token-based billing users. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ModelPickerPriceCategory : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ModelPickerPriceCategory(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the low value. + public static ModelPickerPriceCategory Low { get; } = new("low"); + + /// Gets the medium value. + public static ModelPickerPriceCategory Medium { get; } = new("medium"); + + /// Gets the high value. + public static ModelPickerPriceCategory High { get; } = new("high"); + + /// Gets the very_high value. + public static ModelPickerPriceCategory VeryHigh { get; } = new("very_high"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ModelPickerPriceCategory left, ModelPickerPriceCategory right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ModelPickerPriceCategory left, ModelPickerPriceCategory right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ModelPickerPriceCategory other && Equals(other); + + /// + public bool Equals(ModelPickerPriceCategory other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ModelPickerPriceCategory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ModelPickerPriceCategory value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPickerPriceCategory)); + } + } +} + + +/// Current policy state for this model. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ModelPolicyState : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ModelPolicyState(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the enabled value. + public static ModelPolicyState Enabled { get; } = new("enabled"); + + /// Gets the disabled value. + public static ModelPolicyState Disabled { get; } = new("disabled"); + + /// Gets the unconfigured value. + public static ModelPolicyState Unconfigured { get; } = new("unconfigured"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ModelPolicyState left, ModelPolicyState right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ModelPolicyState left, ModelPolicyState right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ModelPolicyState other && Equals(other); + + /// + public bool Equals(ModelPolicyState other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ModelPolicyState Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ModelPolicyState value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ModelPolicyState)); + } + } +} + + +/// Server transport type: stdio, http, sse, or memory. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct DiscoveredMcpServerType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public DiscoveredMcpServerType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the stdio value. + public static DiscoveredMcpServerType Stdio { get; } = new("stdio"); + + /// Gets the http value. + public static DiscoveredMcpServerType Http { get; } = new("http"); + + /// Gets the sse value. + public static DiscoveredMcpServerType Sse { get; } = new("sse"); + + /// Gets the memory value. + public static DiscoveredMcpServerType Memory { get; } = new("memory"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(DiscoveredMcpServerType left, DiscoveredMcpServerType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(DiscoveredMcpServerType left, DiscoveredMcpServerType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is DiscoveredMcpServerType other && Equals(other); + + /// + public bool Equals(DiscoveredMcpServerType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override DiscoveredMcpServerType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, DiscoveredMcpServerType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(DiscoveredMcpServerType)); + } + } +} + + +/// Path conventions used by this filesystem. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionFsSetProviderConventions : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionFsSetProviderConventions(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the windows value. + public static SessionFsSetProviderConventions Windows { get; } = new("windows"); + + /// Gets the posix value. + public static SessionFsSetProviderConventions Posix { get; } = new("posix"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionFsSetProviderConventions left, SessionFsSetProviderConventions right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionFsSetProviderConventions left, SessionFsSetProviderConventions right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionFsSetProviderConventions other && Equals(other); + + /// + public bool Equals(SessionFsSetProviderConventions other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionFsSetProviderConventions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionFsSetProviderConventions value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSetProviderConventions)); + } + } +} + + +/// Neutral SDK discriminator for the connected remote session kind. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ConnectedRemoteSessionMetadataKind : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ConnectedRemoteSessionMetadataKind(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the remote-session value. + public static ConnectedRemoteSessionMetadataKind RemoteSession { get; } = new("remote-session"); + + /// Gets the coding-agent value. + public static ConnectedRemoteSessionMetadataKind CodingAgent { get; } = new("coding-agent"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ConnectedRemoteSessionMetadataKind left, ConnectedRemoteSessionMetadataKind right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ConnectedRemoteSessionMetadataKind left, ConnectedRemoteSessionMetadataKind right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ConnectedRemoteSessionMetadataKind other && Equals(other); + + /// + public bool Equals(ConnectedRemoteSessionMetadataKind other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ConnectedRemoteSessionMetadataKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ConnectedRemoteSessionMetadataKind value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ConnectedRemoteSessionMetadataKind)); + } + } +} + + +/// Repository host type. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionContextHostType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionContextHostType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the github value. + public static SessionContextHostType Github { get; } = new("github"); + + /// Gets the ado value. + public static SessionContextHostType Ado { get; } = new("ado"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionContextHostType left, SessionContextHostType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionContextHostType left, SessionContextHostType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionContextHostType other && Equals(other); + + /// + public bool Equals(SessionContextHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionContextHostType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionContextHostType)); + } + } +} + + +/// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SendAgentMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SendAgentMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the interactive value. + public static SendAgentMode Interactive { get; } = new("interactive"); + + /// Gets the plan value. + public static SendAgentMode Plan { get; } = new("plan"); + + /// Gets the autopilot value. + public static SendAgentMode Autopilot { get; } = new("autopilot"); + + /// Gets the shell value. + public static SendAgentMode Shell { get; } = new("shell"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SendAgentMode left, SendAgentMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SendAgentMode left, SendAgentMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SendAgentMode other && Equals(other); + + /// + public bool Equals(SendAgentMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SendAgentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SendAgentMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAgentMode)); + } + } +} + + +/// Type of GitHub reference. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SendAttachmentGithubReferenceType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SendAttachmentGithubReferenceType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the issue value. + public static SendAttachmentGithubReferenceType Issue { get; } = new("issue"); + + /// Gets the pr value. + public static SendAttachmentGithubReferenceType Pr { get; } = new("pr"); + + /// Gets the discussion value. + public static SendAttachmentGithubReferenceType Discussion { get; } = new("discussion"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SendAttachmentGithubReferenceType left, SendAttachmentGithubReferenceType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SendAttachmentGithubReferenceType left, SendAttachmentGithubReferenceType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SendAttachmentGithubReferenceType other && Equals(other); + + /// + public bool Equals(SendAttachmentGithubReferenceType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SendAttachmentGithubReferenceType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SendAttachmentGithubReferenceType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendAttachmentGithubReferenceType)); + } + } +} + + +/// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SendMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SendMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the enqueue value. + public static SendMode Enqueue { get; } = new("enqueue"); + + /// Gets the immediate value. + public static SendMode Immediate { get; } = new("immediate"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SendMode left, SendMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SendMode left, SendMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SendMode other && Equals(other); + + /// + public bool Equals(SendMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SendMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SendMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SendMode)); + } + } +} + + +/// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionLogLevel : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionLogLevel(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the info value. + public static SessionLogLevel Info { get; } = new("info"); + + /// Gets the warning value. + public static SessionLogLevel Warning { get; } = new("warning"); + + /// Gets the error value. + public static SessionLogLevel Error { get; } = new("error"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionLogLevel left, SessionLogLevel right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionLogLevel left, SessionLogLevel right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionLogLevel other && Equals(other); + + /// + public bool Equals(SessionLogLevel other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionLogLevel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionLogLevel value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionLogLevel)); + } + } +} + + +/// Authentication type. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct AuthInfoType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public AuthInfoType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the hmac value. + public static AuthInfoType Hmac { get; } = new("hmac"); + + /// Gets the env value. + public static AuthInfoType Env { get; } = new("env"); + + /// Gets the user value. + public static AuthInfoType User { get; } = new("user"); + + /// Gets the gh-cli value. + public static AuthInfoType GhCli { get; } = new("gh-cli"); + + /// Gets the api-key value. + public static AuthInfoType ApiKey { get; } = new("api-key"); + + /// Gets the token value. + public static AuthInfoType Token { get; } = new("token"); + + /// Gets the copilot-api-token value. + public static AuthInfoType CopilotApiToken { get; } = new("copilot-api-token"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(AuthInfoType left, AuthInfoType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(AuthInfoType left, AuthInfoType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is AuthInfoType other && Equals(other); + + /// + public bool Equals(AuthInfoType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override AuthInfoType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, AuthInfoType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AuthInfoType)); + } + } +} + + +/// Defines the allowed values. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct WorkspacesGetWorkspaceResultWorkspaceHostType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public WorkspacesGetWorkspaceResultWorkspaceHostType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the github value. + public static WorkspacesGetWorkspaceResultWorkspaceHostType Github { get; } = new("github"); + + /// Gets the ado value. + public static WorkspacesGetWorkspaceResultWorkspaceHostType Ado { get; } = new("ado"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(WorkspacesGetWorkspaceResultWorkspaceHostType left, WorkspacesGetWorkspaceResultWorkspaceHostType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is WorkspacesGetWorkspaceResultWorkspaceHostType other && Equals(other); + + /// + public bool Equals(WorkspacesGetWorkspaceResultWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override WorkspacesGetWorkspaceResultWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, WorkspacesGetWorkspaceResultWorkspaceHostType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(WorkspacesGetWorkspaceResultWorkspaceHostType)); + } + } +} + + +/// Where this source lives — used for UI grouping. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct InstructionsSourcesLocation : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public InstructionsSourcesLocation(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the user value. + public static InstructionsSourcesLocation User { get; } = new("user"); + + /// Gets the repository value. + public static InstructionsSourcesLocation Repository { get; } = new("repository"); + + /// Gets the working-directory value. + public static InstructionsSourcesLocation WorkingDirectory { get; } = new("working-directory"); + + /// Gets the plugin value. + public static InstructionsSourcesLocation Plugin { get; } = new("plugin"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(InstructionsSourcesLocation left, InstructionsSourcesLocation right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(InstructionsSourcesLocation left, InstructionsSourcesLocation right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is InstructionsSourcesLocation other && Equals(other); + + /// + public bool Equals(InstructionsSourcesLocation other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override InstructionsSourcesLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, InstructionsSourcesLocation value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesLocation)); + } + } +} + + +/// Category of instruction source — used for merge logic. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct InstructionsSourcesType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public InstructionsSourcesType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the home value. + public static InstructionsSourcesType Home { get; } = new("home"); + + /// Gets the repo value. + public static InstructionsSourcesType Repo { get; } = new("repo"); + + /// Gets the model value. + public static InstructionsSourcesType Model { get; } = new("model"); + + /// Gets the vscode value. + public static InstructionsSourcesType Vscode { get; } = new("vscode"); + + /// Gets the nested-agents value. + public static InstructionsSourcesType NestedAgents { get; } = new("nested-agents"); + + /// Gets the child-instructions value. + public static InstructionsSourcesType ChildInstructions { get; } = new("child-instructions"); + + /// Gets the plugin value. + public static InstructionsSourcesType Plugin { get; } = new("plugin"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(InstructionsSourcesType left, InstructionsSourcesType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(InstructionsSourcesType left, InstructionsSourcesType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is InstructionsSourcesType other && Equals(other); + + /// + public bool Equals(InstructionsSourcesType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override InstructionsSourcesType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, InstructionsSourcesType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(InstructionsSourcesType)); + } + } +} + + +/// Where the agent definition was loaded from. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct AgentInfoSource : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public AgentInfoSource(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the user value. + public static AgentInfoSource User { get; } = new("user"); + + /// Gets the project value. + public static AgentInfoSource Project { get; } = new("project"); + + /// Gets the inherited value. + public static AgentInfoSource Inherited { get; } = new("inherited"); + + /// Gets the remote value. + public static AgentInfoSource Remote { get; } = new("remote"); + + /// Gets the plugin value. + public static AgentInfoSource Plugin { get; } = new("plugin"); + + /// Gets the builtin value. + public static AgentInfoSource Builtin { get; } = new("builtin"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(AgentInfoSource left, AgentInfoSource right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(AgentInfoSource left, AgentInfoSource right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is AgentInfoSource other && Equals(other); + + /// + public bool Equals(AgentInfoSource other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override AgentInfoSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, AgentInfoSource value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(AgentInfoSource)); + } + } +} + + +/// Whether task execution is synchronously awaited or managed in the background. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct TaskExecutionMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public TaskExecutionMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the sync value. + public static TaskExecutionMode Sync { get; } = new("sync"); + + /// Gets the background value. + public static TaskExecutionMode Background { get; } = new("background"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(TaskExecutionMode left, TaskExecutionMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(TaskExecutionMode left, TaskExecutionMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is TaskExecutionMode other && Equals(other); + + /// + public bool Equals(TaskExecutionMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override TaskExecutionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, TaskExecutionMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskExecutionMode)); + } + } +} + + +/// Current lifecycle status of the task. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct TaskStatus : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public TaskStatus(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the running value. + public static TaskStatus Running { get; } = new("running"); + + /// Gets the idle value. + public static TaskStatus Idle { get; } = new("idle"); + + /// Gets the completed value. + public static TaskStatus Completed { get; } = new("completed"); + + /// Gets the failed value. + public static TaskStatus Failed { get; } = new("failed"); + + /// Gets the cancelled value. + public static TaskStatus Cancelled { get; } = new("cancelled"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(TaskStatus left, TaskStatus right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(TaskStatus left, TaskStatus right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is TaskStatus other && Equals(other); + + /// + public bool Equals(TaskStatus other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override TaskStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, TaskStatus value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskStatus)); + } + } +} + + +/// Whether the shell runs inside a managed PTY session or as an independent background process. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct TaskShellInfoAttachmentMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public TaskShellInfoAttachmentMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the attached value. + public static TaskShellInfoAttachmentMode Attached { get; } = new("attached"); + + /// Gets the detached value. + public static TaskShellInfoAttachmentMode Detached { get; } = new("detached"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(TaskShellInfoAttachmentMode left, TaskShellInfoAttachmentMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(TaskShellInfoAttachmentMode left, TaskShellInfoAttachmentMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is TaskShellInfoAttachmentMode other && Equals(other); + + /// + public bool Equals(TaskShellInfoAttachmentMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override TaskShellInfoAttachmentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, TaskShellInfoAttachmentMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(TaskShellInfoAttachmentMode)); + } + } +} + + +/// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct McpSamplingExecutionAction : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public McpSamplingExecutionAction(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the success value. + public static McpSamplingExecutionAction Success { get; } = new("success"); + + /// Gets the failure value. + public static McpSamplingExecutionAction Failure { get; } = new("failure"); + + /// Gets the cancelled value. + public static McpSamplingExecutionAction Cancelled { get; } = new("cancelled"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(McpSamplingExecutionAction left, McpSamplingExecutionAction right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(McpSamplingExecutionAction left, McpSamplingExecutionAction right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is McpSamplingExecutionAction other && Equals(other); + + /// + public bool Equals(McpSamplingExecutionAction other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override McpSamplingExecutionAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, McpSamplingExecutionAction value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSamplingExecutionAction)); + } + } +} + + +/// How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct McpSetEnvValueModeDetails : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public McpSetEnvValueModeDetails(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the direct value. + public static McpSetEnvValueModeDetails Direct { get; } = new("direct"); + + /// Gets the indirect value. + public static McpSetEnvValueModeDetails Indirect { get; } = new("indirect"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(McpSetEnvValueModeDetails left, McpSetEnvValueModeDetails right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(McpSetEnvValueModeDetails left, McpSetEnvValueModeDetails right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is McpSetEnvValueModeDetails other && Equals(other); + + /// + public bool Equals(McpSetEnvValueModeDetails other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override McpSetEnvValueModeDetails Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, McpSetEnvValueModeDetails value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(McpSetEnvValueModeDetails)); + } + } +} + + +/// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct OptionsUpdateEnvValueMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public OptionsUpdateEnvValueMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the direct value. + public static OptionsUpdateEnvValueMode Direct { get; } = new("direct"); + + /// Gets the indirect value. + public static OptionsUpdateEnvValueMode Indirect { get; } = new("indirect"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(OptionsUpdateEnvValueMode left, OptionsUpdateEnvValueMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(OptionsUpdateEnvValueMode left, OptionsUpdateEnvValueMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is OptionsUpdateEnvValueMode other && Equals(other); + + /// + public bool Equals(OptionsUpdateEnvValueMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override OptionsUpdateEnvValueMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, OptionsUpdateEnvValueMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(OptionsUpdateEnvValueMode)); + } + } +} + + +/// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/). +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ExtensionSource : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ExtensionSource(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the project value. + public static ExtensionSource Project { get; } = new("project"); + + /// Gets the user value. + public static ExtensionSource User { get; } = new("user"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ExtensionSource left, ExtensionSource right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ExtensionSource left, ExtensionSource right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ExtensionSource other && Equals(other); + + /// + public bool Equals(ExtensionSource other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ExtensionSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ExtensionSource value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionSource)); + } + } +} + + +/// Current status: running, disabled, failed, or starting. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ExtensionStatus : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ExtensionStatus(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the running value. + public static ExtensionStatus Running { get; } = new("running"); + + /// Gets the disabled value. + public static ExtensionStatus Disabled { get; } = new("disabled"); + + /// Gets the failed value. + public static ExtensionStatus Failed { get; } = new("failed"); + + /// Gets the starting value. + public static ExtensionStatus Starting { get; } = new("starting"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ExtensionStatus left, ExtensionStatus right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ExtensionStatus left, ExtensionStatus right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ExtensionStatus other && Equals(other); + + /// + public bool Equals(ExtensionStatus other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ExtensionStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ExtensionStatus value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ExtensionStatus)); + } + } +} + + +/// Optional completion hint for the input (e.g. 'directory' for filesystem path completion). +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SlashCommandInputCompletion : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SlashCommandInputCompletion(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the directory value. + public static SlashCommandInputCompletion Directory { get; } = new("directory"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SlashCommandInputCompletion left, SlashCommandInputCompletion right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SlashCommandInputCompletion left, SlashCommandInputCompletion right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SlashCommandInputCompletion other && Equals(other); + + /// + public bool Equals(SlashCommandInputCompletion other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SlashCommandInputCompletion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SlashCommandInputCompletion value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandInputCompletion)); + } + } +} + + +/// Coarse command category for grouping and behavior: runtime built-in, skill-backed command, or SDK/client-owned command. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SlashCommandKind : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SlashCommandKind(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the builtin value. + public static SlashCommandKind Builtin { get; } = new("builtin"); + + /// Gets the skill value. + public static SlashCommandKind Skill { get; } = new("skill"); + + /// Gets the client value. + public static SlashCommandKind Client { get; } = new("client"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SlashCommandKind left, SlashCommandKind right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SlashCommandKind left, SlashCommandKind right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SlashCommandKind other && Equals(other); + + /// + public bool Equals(SlashCommandKind other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SlashCommandKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SlashCommandKind value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SlashCommandKind)); + } + } +} + + +/// The user's response: accept (submitted), decline (rejected), or cancel (dismissed). +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct UIElicitationResponseAction : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public UIElicitationResponseAction(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the accept value. + public static UIElicitationResponseAction Accept { get; } = new("accept"); + + /// Gets the decline value. + public static UIElicitationResponseAction Decline { get; } = new("decline"); + + /// Gets the cancel value. + public static UIElicitationResponseAction Cancel { get; } = new("cancel"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(UIElicitationResponseAction left, UIElicitationResponseAction right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(UIElicitationResponseAction left, UIElicitationResponseAction right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is UIElicitationResponseAction other && Equals(other); + + /// + public bool Equals(UIElicitationResponseAction other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override UIElicitationResponseAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, UIElicitationResponseAction value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIElicitationResponseAction)); + } + } +} + + +/// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct UIAutoModeSwitchResponse : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public UIAutoModeSwitchResponse(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the yes value. + public static UIAutoModeSwitchResponse Yes { get; } = new("yes"); + + /// Gets the yes_always value. + public static UIAutoModeSwitchResponse YesAlways { get; } = new("yes_always"); + + /// Gets the no value. + public static UIAutoModeSwitchResponse No { get; } = new("no"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(UIAutoModeSwitchResponse left, UIAutoModeSwitchResponse right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(UIAutoModeSwitchResponse left, UIAutoModeSwitchResponse right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is UIAutoModeSwitchResponse other && Equals(other); + + /// + public bool Equals(UIAutoModeSwitchResponse other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override UIAutoModeSwitchResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, UIAutoModeSwitchResponse value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIAutoModeSwitchResponse)); + } + } +} + + +/// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct UIExitPlanModeAction : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public UIExitPlanModeAction(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the exit_only value. + public static UIExitPlanModeAction ExitOnly { get; } = new("exit_only"); + + /// Gets the interactive value. + public static UIExitPlanModeAction Interactive { get; } = new("interactive"); + + /// Gets the autopilot value. + public static UIExitPlanModeAction Autopilot { get; } = new("autopilot"); + + /// Gets the autopilot_fleet value. + public static UIExitPlanModeAction AutopilotFleet { get; } = new("autopilot_fleet"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(UIExitPlanModeAction left, UIExitPlanModeAction right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(UIExitPlanModeAction left, UIExitPlanModeAction right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is UIExitPlanModeAction other && Equals(other); + + /// + public bool Equals(UIExitPlanModeAction other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override UIExitPlanModeAction Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, UIExitPlanModeAction value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(UIExitPlanModeAction)); + } + } +} + + +/// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct PermissionsConfigureAdditionalContentExclusionPolicyScope : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public PermissionsConfigureAdditionalContentExclusionPolicyScope(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the repo value. + public static PermissionsConfigureAdditionalContentExclusionPolicyScope Repo { get; } = new("repo"); + + /// Gets the all value. + public static PermissionsConfigureAdditionalContentExclusionPolicyScope All { get; } = new("all"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(PermissionsConfigureAdditionalContentExclusionPolicyScope left, PermissionsConfigureAdditionalContentExclusionPolicyScope right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(PermissionsConfigureAdditionalContentExclusionPolicyScope left, PermissionsConfigureAdditionalContentExclusionPolicyScope right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is PermissionsConfigureAdditionalContentExclusionPolicyScope other && Equals(other); + + /// + public bool Equals(PermissionsConfigureAdditionalContentExclusionPolicyScope other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override PermissionsConfigureAdditionalContentExclusionPolicyScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, PermissionsConfigureAdditionalContentExclusionPolicyScope value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsConfigureAdditionalContentExclusionPolicyScope)); + } + } +} + + +/// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct PermissionsSetApproveAllSource : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public PermissionsSetApproveAllSource(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the cli_flag value. + public static PermissionsSetApproveAllSource CliFlag { get; } = new("cli_flag"); + + /// Gets the slash_command value. + public static PermissionsSetApproveAllSource SlashCommand { get; } = new("slash_command"); + + /// Gets the autopilot_confirmation value. + public static PermissionsSetApproveAllSource AutopilotConfirmation { get; } = new("autopilot_confirmation"); + + /// Gets the rpc value. + public static PermissionsSetApproveAllSource Rpc { get; } = new("rpc"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(PermissionsSetApproveAllSource left, PermissionsSetApproveAllSource right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(PermissionsSetApproveAllSource left, PermissionsSetApproveAllSource right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is PermissionsSetApproveAllSource other && Equals(other); + + /// + public bool Equals(PermissionsSetApproveAllSource other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override PermissionsSetApproveAllSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, PermissionsSetApproveAllSource value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsSetApproveAllSource)); + } + } +} + + +/// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct PermissionsModifyRulesScope : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public PermissionsModifyRulesScope(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the session value. + public static PermissionsModifyRulesScope Session { get; } = new("session"); + + /// Gets the location value. + public static PermissionsModifyRulesScope Location { get; } = new("location"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(PermissionsModifyRulesScope left, PermissionsModifyRulesScope right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(PermissionsModifyRulesScope left, PermissionsModifyRulesScope right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is PermissionsModifyRulesScope other && Equals(other); + + /// + public bool Equals(PermissionsModifyRulesScope other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override PermissionsModifyRulesScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, PermissionsModifyRulesScope value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(PermissionsModifyRulesScope)); + } + } +} + + +/// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot'). +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct MetadataSnapshotCurrentMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public MetadataSnapshotCurrentMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the interactive value. + public static MetadataSnapshotCurrentMode Interactive { get; } = new("interactive"); + + /// Gets the plan value. + public static MetadataSnapshotCurrentMode Plan { get; } = new("plan"); + + /// Gets the autopilot value. + public static MetadataSnapshotCurrentMode Autopilot { get; } = new("autopilot"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(MetadataSnapshotCurrentMode left, MetadataSnapshotCurrentMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(MetadataSnapshotCurrentMode left, MetadataSnapshotCurrentMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is MetadataSnapshotCurrentMode other && Equals(other); + + /// + public bool Equals(MetadataSnapshotCurrentMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override MetadataSnapshotCurrentMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, MetadataSnapshotCurrentMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotCurrentMode)); + } + } +} + + +/// Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` invocation. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct MetadataSnapshotRemoteMetadataTaskType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public MetadataSnapshotRemoteMetadataTaskType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the cca value. + public static MetadataSnapshotRemoteMetadataTaskType Cca { get; } = new("cca"); + + /// Gets the cli value. + public static MetadataSnapshotRemoteMetadataTaskType Cli { get; } = new("cli"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(MetadataSnapshotRemoteMetadataTaskType left, MetadataSnapshotRemoteMetadataTaskType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(MetadataSnapshotRemoteMetadataTaskType left, MetadataSnapshotRemoteMetadataTaskType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is MetadataSnapshotRemoteMetadataTaskType other && Equals(other); + + /// + public bool Equals(MetadataSnapshotRemoteMetadataTaskType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override MetadataSnapshotRemoteMetadataTaskType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, MetadataSnapshotRemoteMetadataTaskType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(MetadataSnapshotRemoteMetadataTaskType)); + } + } +} + + +/// Repository host type, if known. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionMetadataSnapshotWorkspaceHostType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionMetadataSnapshotWorkspaceHostType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the github value. + public static SessionMetadataSnapshotWorkspaceHostType Github { get; } = new("github"); + + /// Gets the ado value. + public static SessionMetadataSnapshotWorkspaceHostType Ado { get; } = new("ado"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionMetadataSnapshotWorkspaceHostType left, SessionMetadataSnapshotWorkspaceHostType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionMetadataSnapshotWorkspaceHostType other && Equals(other); + + /// + public bool Equals(SessionMetadataSnapshotWorkspaceHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionMetadataSnapshotWorkspaceHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionMetadataSnapshotWorkspaceHostType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionMetadataSnapshotWorkspaceHostType)); + } + } +} + + +/// Hosting platform type of the repository. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionWorkingDirectoryContextHostType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionWorkingDirectoryContextHostType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the github value. + public static SessionWorkingDirectoryContextHostType Github { get; } = new("github"); + + /// Gets the ado value. + public static SessionWorkingDirectoryContextHostType Ado { get; } = new("ado"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionWorkingDirectoryContextHostType left, SessionWorkingDirectoryContextHostType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionWorkingDirectoryContextHostType left, SessionWorkingDirectoryContextHostType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionWorkingDirectoryContextHostType other && Equals(other); + + /// + public bool Equals(SessionWorkingDirectoryContextHostType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionWorkingDirectoryContextHostType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionWorkingDirectoryContextHostType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionWorkingDirectoryContextHostType)); + } + } +} + + +/// Signal to send (default: SIGTERM). +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct ShellKillSignal : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public ShellKillSignal(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the SIGTERM value. + public static ShellKillSignal SIGTERM { get; } = new("SIGTERM"); + + /// Gets the SIGKILL value. + public static ShellKillSignal SIGKILL { get; } = new("SIGKILL"); + + /// Gets the SIGINT value. + public static ShellKillSignal SIGINT { get; } = new("SIGINT"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(ShellKillSignal left, ShellKillSignal right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(ShellKillSignal left, ShellKillSignal right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is ShellKillSignal other && Equals(other); + + /// + public bool Equals(ShellKillSignal other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override ShellKillSignal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, ShellKillSignal value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(ShellKillSignal)); + } + } +} + + +/// Whether this item is a queued user message or a queued slash command / model change. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct QueuePendingItemsKind : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public QueuePendingItemsKind(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the message value. + public static QueuePendingItemsKind Message { get; } = new("message"); + + /// Gets the command value. + public static QueuePendingItemsKind Command { get; } = new("command"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(QueuePendingItemsKind left, QueuePendingItemsKind right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(QueuePendingItemsKind left, QueuePendingItemsKind right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is QueuePendingItemsKind other && Equals(other); + + /// + public bool Equals(QueuePendingItemsKind other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override QueuePendingItemsKind Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, QueuePendingItemsKind value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(QueuePendingItemsKind)); + } + } +} + + +/// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct EventsCursorStatus : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public EventsCursorStatus(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the ok value. + public static EventsCursorStatus Ok { get; } = new("ok"); + + /// Gets the expired value. + public static EventsCursorStatus Expired { get; } = new("expired"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(EventsCursorStatus left, EventsCursorStatus right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(EventsCursorStatus left, EventsCursorStatus right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is EventsCursorStatus other && Equals(other); + + /// + public bool Equals(EventsCursorStatus other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override EventsCursorStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, EventsCursorStatus value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsCursorStatus)); + } + } +} + + +/// Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct EventsAgentScope : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public EventsAgentScope(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the primary value. + public static EventsAgentScope Primary { get; } = new("primary"); + + /// Gets the all value. + public static EventsAgentScope All { get; } = new("all"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(EventsAgentScope left, EventsAgentScope right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(EventsAgentScope left, EventsAgentScope right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is EventsAgentScope other && Equals(other); + + /// + public bool Equals(EventsAgentScope other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override EventsAgentScope Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, EventsAgentScope value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(EventsAgentScope)); + } + } +} + + +/// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. +[Experimental(Diagnostics.Experimental)] +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct RemoteSessionMode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public RemoteSessionMode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the off value. + public static RemoteSessionMode Off { get; } = new("off"); + + /// Gets the export value. + public static RemoteSessionMode Export { get; } = new("export"); + + /// Gets the on value. + public static RemoteSessionMode On { get; } = new("on"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(RemoteSessionMode left, RemoteSessionMode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(RemoteSessionMode left, RemoteSessionMode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is RemoteSessionMode other && Equals(other); + + /// + public bool Equals(RemoteSessionMode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override RemoteSessionMode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, RemoteSessionMode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(RemoteSessionMode)); + } + } +} + + +/// Error classification. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionFsErrorCode : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionFsErrorCode(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the ENOENT value. + public static SessionFsErrorCode ENOENT { get; } = new("ENOENT"); + + /// Gets the UNKNOWN value. + public static SessionFsErrorCode UNKNOWN { get; } = new("UNKNOWN"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionFsErrorCode left, SessionFsErrorCode right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionFsErrorCode left, SessionFsErrorCode right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionFsErrorCode other && Equals(other); + + /// + public bool Equals(SessionFsErrorCode other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionFsErrorCode Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionFsErrorCode value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsErrorCode)); + } + } +} + + +/// Entry type. +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionFsReaddirWithTypesEntryType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionFsReaddirWithTypesEntryType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the file value. + public static SessionFsReaddirWithTypesEntryType File { get; } = new("file"); + + /// Gets the directory value. + public static SessionFsReaddirWithTypesEntryType Directory { get; } = new("directory"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionFsReaddirWithTypesEntryType left, SessionFsReaddirWithTypesEntryType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionFsReaddirWithTypesEntryType left, SessionFsReaddirWithTypesEntryType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionFsReaddirWithTypesEntryType other && Equals(other); + + /// + public bool Equals(SessionFsReaddirWithTypesEntryType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionFsReaddirWithTypesEntryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionFsReaddirWithTypesEntryType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsReaddirWithTypesEntryType)); + } + } +} + + +/// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected). +[JsonConverter(typeof(Converter))] +[DebuggerDisplay("{Value,nq}")] +public readonly struct SessionFsSqliteQueryType : IEquatable +{ + private readonly string? _value; + + /// Initializes a new instance of the struct. + /// The value to associate with this . + [JsonConstructor] + public SessionFsSqliteQueryType(string value) + { + ArgumentException.ThrowIfNullOrWhiteSpace(value); + _value = value; + } + + /// Gets the value associated with this . + public string Value => _value ?? string.Empty; + + /// Gets the exec value. + public static SessionFsSqliteQueryType Exec { get; } = new("exec"); + + /// Gets the query value. + public static SessionFsSqliteQueryType Query { get; } = new("query"); + + /// Gets the run value. + public static SessionFsSqliteQueryType Run { get; } = new("run"); + + /// Returns a value indicating whether two instances are equivalent. + public static bool operator ==(SessionFsSqliteQueryType left, SessionFsSqliteQueryType right) => left.Equals(right); + + /// Returns a value indicating whether two instances are not equivalent. + public static bool operator !=(SessionFsSqliteQueryType left, SessionFsSqliteQueryType right) => !(left == right); + + /// + public override bool Equals(object? obj) => obj is SessionFsSqliteQueryType other && Equals(other); + + /// + public bool Equals(SessionFsSqliteQueryType other) => string.Equals(Value, other.Value, StringComparison.OrdinalIgnoreCase); + + /// + public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value); + + /// + public override string ToString() => Value; + + /// Provides a for serializing instances. + [EditorBrowsable(EditorBrowsableState.Never)] + public sealed class Converter : JsonConverter + { + /// + public override SessionFsSqliteQueryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); + } + + /// + public override void Write(Utf8JsonWriter writer, SessionFsSqliteQueryType value, JsonSerializerOptions options) + { + GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); + } + } +} + + +/// Provides server-scoped RPC methods (no session required). +public sealed class ServerRpc +{ + private readonly JsonRpc _rpc; + + internal ServerRpc(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Checks server responsiveness and returns protocol information. + /// Optional message to echo back. + /// The to monitor for cancellation requests. The default is . + /// Server liveness response, including the echoed message, current server timestamp, and protocol version. + public async Task PingAsync(string? message = null, CancellationToken cancellationToken = default) + { + var request = new PingRequest { Message = message }; + return await CopilotClient.InvokeRpcAsync(_rpc, "ping", [request], cancellationToken); + } + + /// Performs the SDK server connection handshake and validates the optional connection token. + /// Connection token; required when the server was started with COPILOT_CONNECTION_TOKEN. + /// The to monitor for cancellation requests. The default is . + /// Handshake result reporting the server's protocol version and package version on success. + internal async Task ConnectAsync(string? token = null, CancellationToken cancellationToken = default) + { + var request = new ConnectRequest { Token = token }; + return await CopilotClient.InvokeRpcAsync(_rpc, "connect", [request], cancellationToken); + } + + /// Models APIs. + public ServerModelsApi Models => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// Tools APIs. + public ServerToolsApi Tools => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// Account APIs. + public ServerAccountApi Account => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// Mcp APIs. + public ServerMcpApi Mcp => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// Skills APIs. + public ServerSkillsApi Skills => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// SessionFs APIs. + public ServerSessionFsApi SessionFs => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; + + /// Sessions APIs. + public ServerSessionsApi Sessions => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; +} + +/// Provides server-scoped Models APIs. +public sealed class ServerModelsApi +{ + private readonly JsonRpc _rpc; + + internal ServerModelsApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Lists Copilot models available to the authenticated user. + /// GitHub token for per-user model listing. When provided, resolves this token to determine the user's Copilot plan and available models instead of using the global auth. + /// The to monitor for cancellation requests. The default is . + /// List of Copilot models available to the resolved user, including capabilities and billing metadata. + public async Task ListAsync(string? gitHubToken = null, CancellationToken cancellationToken = default) + { + var request = new ModelsListRequest { GitHubToken = gitHubToken }; + return await CopilotClient.InvokeRpcAsync(_rpc, "models.list", [request], cancellationToken); + } +} + +/// Provides server-scoped Tools APIs. +public sealed class ServerToolsApi +{ + private readonly JsonRpc _rpc; + + internal ServerToolsApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Lists built-in tools available for a model. + /// Optional model ID — when provided, the returned tool list reflects model-specific overrides. + /// The to monitor for cancellation requests. The default is . + /// Built-in tools available for the requested model, with their parameters and instructions. + 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); + } +} + +/// Provides server-scoped Account APIs. +public sealed class ServerAccountApi +{ + private readonly JsonRpc _rpc; + + internal ServerAccountApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Gets Copilot quota usage for the authenticated user or supplied GitHub token. + /// GitHub token for per-user quota lookup. When provided, resolves this token to determine the user's quota instead of using the global auth. + /// The to monitor for cancellation requests. The default is . + /// Quota usage snapshots for the resolved user, keyed by quota type. + public async Task GetQuotaAsync(string? gitHubToken = null, CancellationToken cancellationToken = default) + { + var request = new AccountGetQuotaRequest { GitHubToken = gitHubToken }; + return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [request], cancellationToken); + } +} + +/// Provides server-scoped Mcp APIs. +public sealed class ServerMcpApi +{ + private readonly JsonRpc _rpc; + + internal ServerMcpApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Discovers MCP servers from user, workspace, plugin, and builtin sources. + /// Working directory used as context for discovery (e.g., plugin resolution). + /// The to monitor for cancellation requests. The default is . + /// MCP servers discovered from user, workspace, plugin, and built-in sources. + 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); + } + + /// Config APIs. + public ServerMcpConfigApi Config => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; +} + +/// Provides server-scoped McpConfig APIs. +public sealed class ServerMcpConfigApi +{ + private readonly JsonRpc _rpc; + + internal ServerMcpConfigApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Lists MCP servers from user configuration. + /// The to monitor for cancellation requests. The default is . + /// User-configured MCP servers, keyed by server name. + public async Task ListAsync(CancellationToken cancellationToken = default) + { + return await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.list", [], cancellationToken); + } + + /// Adds an MCP server to user configuration. + /// Unique name for the MCP server. + /// MCP server configuration (stdio process or remote HTTP/SSE). + /// The to monitor for cancellation requests. The default is . + public async Task AddAsync(string name, object config, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(config); + + var request = new McpConfigAddRequest { Name = name, Config = config }; + await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.add", [request], cancellationToken); + } + + /// Updates an MCP server in user configuration. + /// Name of the MCP server to update. + /// MCP server configuration (stdio process or remote HTTP/SSE). + /// The to monitor for cancellation requests. The default is . + public async Task UpdateAsync(string name, object config, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(config); + + var request = new McpConfigUpdateRequest { Name = name, Config = config }; + await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.update", [request], cancellationToken); + } + + /// Removes an MCP server from user configuration. + /// Name of the MCP server to remove. + /// The to monitor for cancellation requests. The default is . + public async Task RemoveAsync(string name, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(name); + + var request = new McpConfigRemoveRequest { Name = name }; + await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.remove", [request], cancellationToken); + } + + /// Enables MCP servers in user configuration for new sessions. + /// Names of MCP servers to enable. Each server is removed from the persisted disabled list so new sessions spawn it. Unknown or already-enabled names are ignored. + /// The to monitor for cancellation requests. The default is . + public async Task EnableAsync(IList names, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(names); + + var request = new McpConfigEnableRequest { Names = names }; + await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.enable", [request], cancellationToken); + } + + /// Disables MCP servers in user configuration for new sessions. + /// Names of MCP servers to disable. Each server is added to the persisted disabled list so new sessions skip it. Already-disabled names are ignored. Active sessions keep their current connections until they end. + /// The to monitor for cancellation requests. The default is . + public async Task DisableAsync(IList names, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(names); + + var request = new McpConfigDisableRequest { Names = names }; + await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.disable", [request], cancellationToken); + } +} + +/// Provides server-scoped Skills APIs. +public sealed class ServerSkillsApi +{ + private readonly JsonRpc _rpc; + + internal ServerSkillsApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Discovers skills across global and project sources. + /// Optional list of project directory paths to scan for project-scoped skills. + /// Optional list of additional skill directory paths to include. + /// The to monitor for cancellation requests. The default is . + /// Skills discovered across global and project sources. + public async Task DiscoverAsync(IList? projectPaths = null, IList? skillDirectories = null, CancellationToken cancellationToken = default) + { + var request = new SkillsDiscoverRequest { ProjectPaths = projectPaths, SkillDirectories = skillDirectories }; + return await CopilotClient.InvokeRpcAsync(_rpc, "skills.discover", [request], cancellationToken); + } + + /// Config APIs. + public ServerSkillsConfigApi Config => + field ?? + Interlocked.CompareExchange(ref field, new(_rpc), null) ?? + field; +} + +/// Provides server-scoped SkillsConfig APIs. +public sealed class ServerSkillsConfigApi +{ + private readonly JsonRpc _rpc; + + internal ServerSkillsConfigApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Replaces the global list of disabled skills. + /// List of skill names to disable. + /// The to monitor for cancellation requests. The default is . + public async Task SetDisabledSkillsAsync(IList disabledSkills, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(disabledSkills); + + var request = new SkillsConfigSetDisabledSkillsRequest { DisabledSkills = disabledSkills }; + await CopilotClient.InvokeRpcAsync(_rpc, "skills.config.setDisabledSkills", [request], cancellationToken); + } +} + +/// Provides server-scoped SessionFs APIs. +public sealed class ServerSessionFsApi +{ + private readonly JsonRpc _rpc; + + internal ServerSessionFsApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Registers an SDK client as the session filesystem provider. + /// Initial working directory for sessions. + /// Path within each session's SessionFs where the runtime stores files for that session. + /// Path conventions used by this filesystem. + /// Optional capabilities declared by the provider. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the calling client was registered as the session filesystem provider. + public async Task SetProviderAsync(string initialCwd, string sessionStatePath, SessionFsSetProviderConventions conventions, SessionFsSetProviderCapabilities? capabilities = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(initialCwd); + ArgumentNullException.ThrowIfNull(sessionStatePath); + + var request = new SessionFsSetProviderRequest { InitialCwd = initialCwd, SessionStatePath = sessionStatePath, Conventions = conventions, Capabilities = capabilities }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessionFs.setProvider", [request], cancellationToken); + } +} + +/// Provides server-scoped Sessions APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class ServerSessionsApi +{ + private readonly JsonRpc _rpc; + + internal ServerSessionsApi(JsonRpc rpc) + { + _rpc = rpc; + } + + /// Creates a new session by forking persisted history from an existing session. + /// Source session ID to fork from. + /// Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. + /// Optional friendly name to assign to the forked session. + /// The to monitor for cancellation requests. The default is . + /// Identifier and optional friendly name assigned to the newly forked session. + public async Task ForkAsync(string sessionId, string? toEventId = null, string? name = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsForkRequest { SessionId = sessionId, ToEventId = toEventId, Name = name }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.fork", [request], cancellationToken); + } + + /// Connects to an existing remote session and exposes it as an SDK session. + /// Session ID to connect to. + /// The to monitor for cancellation requests. The default is . + /// Remote session connection result. + public async Task ConnectAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new ConnectRemoteSessionParams { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.connect", [request], cancellationToken); + } + + /// Lists persisted sessions, optionally filtered by working-directory context. + /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. + /// Optional filter applied to the returned sessions. + /// The to monitor for cancellation requests. The default is . + /// Persisted sessions matching the filter, ordered most-recently-modified first. + public async Task ListAsync(long? metadataLimit = null, SessionsListRequestFilter? filter = null, CancellationToken cancellationToken = default) + { + var request = new SessionsListRequest { MetadataLimit = metadataLimit, Filter = filter }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.list", [request], cancellationToken); + } + + /// Finds the local session bound to a GitHub task ID, if any. + /// GitHub task ID to look up. + /// The to monitor for cancellation requests. The default is . + /// ID of the local session bound to the given GitHub task, or omitted when none. + public async Task FindByTaskIdAsync(string taskId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(taskId); + + var request = new SessionsFindByTaskIDRequest { TaskId = taskId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.findByTaskId", [request], cancellationToken); + } + + /// Resolves a UUID prefix to a unique session ID, if exactly one session matches. + /// UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when there is no match or the prefix matches multiple sessions. + /// The to monitor for cancellation requests. The default is . + /// Session ID matching the prefix, omitted when no unique match exists. + public async Task FindByPrefixAsync(string prefix, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(prefix); + + var request = new SessionsFindByPrefixRequest { Prefix = prefix }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.findByPrefix", [request], cancellationToken); + } + + /// Returns the most-relevant prior session for a given working-directory context. + /// Optional working-directory context used to score session relevance. When omitted the most-recently-modified session wins. + /// The to monitor for cancellation requests. The default is . + /// Most-relevant session ID for the supplied context, or omitted when no sessions exist. + public async Task GetLastForContextAsync(SessionContext? context = null, CancellationToken cancellationToken = default) + { + var request = new SessionsGetLastForContextRequest { Context = context }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.getLastForContext", [request], cancellationToken); + } + + /// Computes the absolute path to a session's persisted events.jsonl file. + /// Session ID whose event-log file path to compute. + /// The to monitor for cancellation requests. The default is . + /// Absolute path to the session's events.jsonl file on disk. + public async Task GetEventFilePathAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsGetEventFilePathRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.getEventFilePath", [request], cancellationToken); + } + + /// Returns the on-disk byte size of each session's workspace directory. + /// The to monitor for cancellation requests. The default is . + /// Map of sessionId -> on-disk size in bytes for each session's workspace directory. + public async Task GetSizesAsync(CancellationToken cancellationToken = default) + { + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.getSizes", [], cancellationToken); + } + + /// Returns the subset of the supplied session IDs that are currently held by another running process. + /// Session IDs to test for live in-use locks. + /// The to monitor for cancellation requests. The default is . + /// Session IDs from the input set that are currently in use by another process. + public async Task CheckInUseAsync(IList sessionIds, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionIds); + + var request = new SessionsCheckInUseRequest { SessionIds = sessionIds }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.checkInUse", [request], cancellationToken); + } + + /// Returns a session's persisted remote-steerable flag, if any has been recorded. + /// Session ID to look up the persisted remote-steerable flag for. + /// The to monitor for cancellation requests. The default is . + /// The session's persisted remote-steerable flag, or omitted when no value has been persisted. + public async Task GetPersistedRemoteSteerableAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsGetPersistedRemoteSteerableRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.getPersistedRemoteSteerable", [request], cancellationToken); + } + + /// Closes a session: emits shutdown, flushes pending events, releases the in-use lock, and disposes the active session. + /// Session ID to close. + /// The to monitor for cancellation requests. The default is . + /// Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. + public async Task CloseAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsCloseRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.close", [request], cancellationToken); + } + + /// Closes, deactivates, and deletes a set of sessions, returning the bytes freed per session. + /// Session IDs to close, deactivate, and delete from disk. + /// The to monitor for cancellation requests. The default is . + /// Map of sessionId -> bytes freed by removing the session's workspace directory. + public async Task BulkDeleteAsync(IList sessionIds, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionIds); + + var request = new SessionsBulkDeleteRequest { SessionIds = sessionIds }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.bulkDelete", [request], cancellationToken); + } + + /// Deletes sessions older than the given threshold, with optional dry-run and exclusion list. + /// Delete sessions whose modifiedTime is at least this many days old. + /// When true, only report what would be deleted without performing any deletion. + /// When true, named sessions (set via /rename) are also eligible for pruning. + /// Session IDs that should never be considered for pruning. + /// The to monitor for cancellation requests. The default is . + /// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. + public async Task PruneOldAsync(long olderThanDays, bool? dryRun = null, bool? includeNamed = null, IList? excludeSessionIds = null, CancellationToken cancellationToken = default) + { + var request = new SessionsPruneOldRequest { OlderThanDays = olderThanDays, DryRun = dryRun, IncludeNamed = includeNamed, ExcludeSessionIds = excludeSessionIds }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.pruneOld", [request], cancellationToken); + } + + /// Flushes a session's pending events to disk. + /// Session ID whose pending events should be flushed to disk. + /// The to monitor for cancellation requests. The default is . + /// Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). + public async Task SaveAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsSaveRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.save", [request], cancellationToken); + } + + /// Releases the in-use lock held by this process for a session. + /// Session ID whose in-use lock should be released. + /// The to monitor for cancellation requests. The default is . + /// Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. + public async Task ReleaseLockAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsReleaseLockRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.releaseLock", [request], cancellationToken); + } + + /// Backfills missing summary and context fields on the supplied session metadata records. + /// Session metadata records to enrich. Records that already have summary and context are returned unchanged. + /// The to monitor for cancellation requests. The default is . + /// The same metadata records, with summary and context fields backfilled where available. + public async Task EnrichMetadataAsync(IList sessions, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessions); + + var request = new SessionsEnrichMetadataRequest { Sessions = sessions }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.enrichMetadata", [request], cancellationToken); + } + + /// Reloads user, plugin, and (optionally) repo hooks on the active session. + /// Active session ID to reload hooks for. + /// When true, skip repo-level hooks. Use before folder trust is confirmed; loadDeferredRepoHooks loads them post-trust. + /// The to monitor for cancellation requests. The default is . + /// Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. + public async Task ReloadPluginHooksAsync(string sessionId, bool? deferRepoHooks = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsReloadPluginHooksRequest { SessionId = sessionId, DeferRepoHooks = deferRepoHooks }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.reloadPluginHooks", [request], cancellationToken); + } + + /// Loads previously-deferred repo-level hooks on the active session, returning queued startup prompts. + /// Active session ID whose deferred repo-level hooks should be loaded. + /// The to monitor for cancellation requests. The default is . + /// Queued repo-level startup prompts and the total hook command count after loading. + public async Task LoadDeferredRepoHooksAsync(string sessionId, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(sessionId); + + var request = new SessionsLoadDeferredRepoHooksRequest { SessionId = sessionId }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.loadDeferredRepoHooks", [request], cancellationToken); + } + + /// Replaces the manager-wide additional plugins registered with the session manager. + /// Manager-wide additional plugins to register. Replaces any previously-configured set. Pass an empty array to clear. + /// The to monitor for cancellation requests. The default is . + /// Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. + public async Task SetAdditionalPluginsAsync(IList plugins, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(plugins); + + var request = new SessionsSetAdditionalPluginsRequest { Plugins = plugins }; + return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.setAdditionalPlugins", [request], cancellationToken); + } +} + +/// Provides typed session-scoped RPC methods. +public sealed class SessionRpc +{ + private readonly CopilotSession _session; + + internal SessionRpc(CopilotSession session) + { + _session = session; + } + + internal CopilotSession Session => _session; + + /// Auth APIs. + public AuthApi Auth => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Model APIs. + public ModelApi Model => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Mode APIs. + public ModeApi Mode => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Name APIs. + public NameApi Name => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Plan APIs. + public PlanApi Plan => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Workspaces APIs. + public WorkspacesApi Workspaces => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Instructions APIs. + public InstructionsApi Instructions => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Fleet APIs. + public FleetApi Fleet => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Agent APIs. + public AgentApi Agent => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Tasks APIs. + public TasksApi Tasks => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Skills APIs. + public SkillsApi Skills => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Mcp APIs. + public McpApi Mcp => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Plugins APIs. + public PluginsApi Plugins => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Options APIs. + public OptionsApi Options => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Lsp APIs. + public LspApi Lsp => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Extensions APIs. + public ExtensionsApi Extensions => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Tools APIs. + public ToolsApi Tools => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Commands APIs. + public CommandsApi Commands => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Telemetry APIs. + public TelemetryApi Telemetry => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Ui APIs. + public UiApi Ui => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Permissions APIs. + public PermissionsApi Permissions => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Metadata APIs. + public MetadataApi Metadata => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Shell APIs. + public ShellApi Shell => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// History APIs. + public HistoryApi History => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Queue APIs. + public QueueApi Queue => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// EventLog APIs. + public EventLogApi EventLog => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Usage APIs. + public UsageApi Usage => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Remote APIs. + public RemoteApi Remote => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Schedule APIs. + public ScheduleApi Schedule => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Suspends the session while preserving persisted state for later resume. + /// The to monitor for cancellation requests. The default is . + public async Task SuspendAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionSuspendRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.suspend", [request], cancellationToken); + } + + /// Sends a user message to the session and returns its message ID. + /// The user message text. + /// If provided, this is shown in the timeline instead of `prompt`. + /// Optional attachments (files, directories, selections, blobs, GitHub references) to include with the message. + /// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. + /// If true, adds the message to the front of the queue instead of the end. + /// If false, this message will not trigger a Premium Request Unit charge. User messages default to billable. + /// If set, the request will fail if the named tool is not available when this message is among the user messages at the start of the current exchange. + /// Optional provenance tag copied to the resulting user.message event. Supported values are `system`, `command-*`, and `schedule-*`. + /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. + /// Custom HTTP headers to include in outbound model requests for this turn. Merged with session-level provider headers; per-turn headers augment and overwrite session-level headers with the same key. + /// W3C Trace Context traceparent header for distributed tracing of this agent turn. + /// W3C Trace Context tracestate header for distributed tracing. + /// If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. + /// The to monitor for cancellation requests. The default is . + /// Result of sending a user message. + public async Task SendAsync(string prompt, string? displayPrompt = null, IList? attachments = null, SendMode? mode = null, bool? prepend = null, bool? billable = null, string? requiredTool = null, object? source = null, SendAgentMode? agentMode = null, IDictionary? requestHeaders = null, string? traceparent = null, string? tracestate = null, bool? wait = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(prompt); + _session.ThrowIfDisposed(); + + var request = new SendRequest { SessionId = _session.SessionId, Prompt = prompt, DisplayPrompt = displayPrompt, Attachments = attachments, Mode = mode, Prepend = prepend, Billable = billable, RequiredTool = requiredTool, Source = source, AgentMode = agentMode, RequestHeaders = requestHeaders, Traceparent = traceparent, Tracestate = tracestate, Wait = wait }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.send", [request], cancellationToken); + } + + /// Aborts the current agent turn. + /// Finite reason code describing why the current turn was aborted. + /// The to monitor for cancellation requests. The default is . + /// Result of aborting the current turn. + public async Task AbortAsync(AbortReason? reason = null, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new AbortRequest { SessionId = _session.SessionId, Reason = reason }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.abort", [request], cancellationToken); + } + + /// Shuts down the session and persists its final state. Awaits any deferred sessionEnd hooks before resolving so user-supplied hook scripts complete before the runtime tears down. + /// Why the session is being shut down. Defaults to "routine" when omitted. + /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. + /// The to monitor for cancellation requests. The default is . + public async Task ShutdownAsync(ShutdownType? type = null, string? reason = null, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// - public override string ToString() => Value; + var request = new ShutdownRequest { SessionId = _session.SessionId, Type = type, Reason = reason }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.shutdown", [request], cancellationToken); + } - /// Provides a for serializing instances. - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class Converter : JsonConverter + /// Emits a user-visible session log event. + /// Human-readable message. + /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". + /// Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". + /// When true, the message is transient and not persisted to the session event log on disk. + /// Optional URL the user can open in their browser for more details. + /// Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. + /// The to monitor for cancellation requests. The default is . + /// Identifier of the session event that was emitted for the log message. + public async Task LogAsync(string message, SessionLogLevel? level = null, string? type = null, bool? ephemeral = null, string? url = null, string? tip = null, CancellationToken cancellationToken = default) { - /// - public override SessionFsSqliteQueryType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return new(GitHub.Copilot.SDK.GeneratedStringEnumJson.ReadValue(ref reader, typeToConvert)); - } + ArgumentNullException.ThrowIfNull(message); + _session.ThrowIfDisposed(); - /// - public override void Write(Utf8JsonWriter writer, SessionFsSqliteQueryType value, JsonSerializerOptions options) - { - GitHub.Copilot.SDK.GeneratedStringEnumJson.WriteValue(writer, value.Value, typeof(SessionFsSqliteQueryType)); - } + var request = new LogRequest { SessionId = _session.SessionId, Message = message, Level = level, Type = type, Ephemeral = ephemeral, Url = url, Tip = tip }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.log", [request], cancellationToken); } } - -/// Provides server-scoped RPC methods (no session required). -public sealed class ServerRpc +/// Provides session-scoped Auth APIs. +public sealed class AuthApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerRpc(JsonRpc rpc) + internal AuthApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Checks server responsiveness and returns protocol information. - /// Optional message to echo back. + /// Gets authentication status and account metadata for the session. /// The to monitor for cancellation requests. The default is . - /// Server liveness response, including the echoed message, current timestamp, and protocol version. - public async Task PingAsync(string? message = null, CancellationToken cancellationToken = default) + /// Authentication status and account metadata for the session. + public async Task GetStatusAsync(CancellationToken cancellationToken = default) { - var request = new PingRequest { Message = message }; - return await CopilotClient.InvokeRpcAsync(_rpc, "ping", [request], cancellationToken); + _session.ThrowIfDisposed(); + + var request = new SessionAuthGetStatusRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.auth.getStatus", [request], cancellationToken); } - /// Performs the SDK server connection handshake and validates the optional connection token. - /// Connection token; required when the server was started with COPILOT_CONNECTION_TOKEN. + /// Updates the session's auth credentials used for outbound model and API requests. + /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. /// The to monitor for cancellation requests. The default is . - /// Handshake result reporting the server's protocol version and package version on success. - internal async Task ConnectAsync(string? token = null, CancellationToken cancellationToken = default) + /// Indicates whether the credential update succeeded. + public async Task SetCredentialsAsync(AuthInfo? credentials = null, CancellationToken cancellationToken = default) { - var request = new ConnectRequest { Token = token }; - return await CopilotClient.InvokeRpcAsync(_rpc, "connect", [request], cancellationToken); + _session.ThrowIfDisposed(); + + var request = new SessionSetCredentialsParams { SessionId = _session.SessionId, Credentials = credentials }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.auth.setCredentials", [request], cancellationToken); } +} - /// Models APIs. - public ServerModelsApi Models => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; +/// Provides session-scoped Model APIs. +public sealed class ModelApi +{ + private readonly CopilotSession _session; - /// Tools APIs. - public ServerToolsApi Tools => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + internal ModelApi(CopilotSession session) + { + _session = session; + } - /// Account APIs. - public ServerAccountApi Account => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + /// Gets the currently selected model for the session. + /// The to monitor for cancellation requests. The default is . + /// The currently selected model and reasoning effort for the session. + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Mcp APIs. - public ServerMcpApi Mcp => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + var request = new SessionModelGetCurrentRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.model.getCurrent", [request], cancellationToken); + } - /// Skills APIs. - public ServerSkillsApi Skills => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + /// Switches the session to a model and optional reasoning configuration. + /// Model identifier to switch to. + /// Reasoning effort level to use for the model. "none" disables reasoning. + /// Reasoning summary mode to request for supported model clients. + /// Override individual model capabilities resolved by the runtime. + /// The to monitor for cancellation requests. The default is . + /// The model identifier active on the session after the switch. + public async Task SwitchToAsync(string modelId, string? reasoningEffort = null, ReasoningSummary? reasoningSummary = null, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(modelId); + _session.ThrowIfDisposed(); - /// SessionFs APIs. - public ServerSessionFsApi SessionFs => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + var request = new ModelSwitchToRequest { SessionId = _session.SessionId, ModelId = modelId, ReasoningEffort = reasoningEffort, ReasoningSummary = reasoningSummary, ModelCapabilities = modelCapabilities }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.model.switchTo", [request], cancellationToken); + } - /// Sessions APIs. - public ServerSessionsApi Sessions => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + /// Updates the session's reasoning effort without changing the selected model. + /// Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. + /// The to monitor for cancellation requests. The default is . + /// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. + public async Task SetReasoningEffortAsync(string reasoningEffort, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(reasoningEffort); + _session.ThrowIfDisposed(); + + var request = new ModelSetReasoningEffortRequest { SessionId = _session.SessionId, ReasoningEffort = reasoningEffort }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.model.setReasoningEffort", [request], cancellationToken); + } } -/// Provides server-scoped Models APIs. -public sealed class ServerModelsApi +/// Provides session-scoped Mode APIs. +public sealed class ModeApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerModelsApi(JsonRpc rpc) + internal ModeApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Lists Copilot models available to the authenticated user. - /// GitHub token for per-user model listing. When provided, resolves this token to determine the user's Copilot plan and available models instead of using the global auth. + /// Gets the current agent interaction mode. /// The to monitor for cancellation requests. The default is . - /// List of Copilot models available to the resolved user, including capabilities and billing metadata. - public async Task ListAsync(string? gitHubToken = null, CancellationToken cancellationToken = default) + /// The session mode the agent is operating in. + public async Task GetAsync(CancellationToken cancellationToken = default) { - var request = new ModelsListRequest { GitHubToken = gitHubToken }; - return await CopilotClient.InvokeRpcAsync(_rpc, "models.list", [request], cancellationToken); + _session.ThrowIfDisposed(); + + var request = new SessionModeGetRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mode.get", [request], cancellationToken); + } + + /// Sets the current agent interaction mode. + /// The session mode the agent is operating in. + /// The to monitor for cancellation requests. The default is . + public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new ModeSetRequest { SessionId = _session.SessionId, Mode = mode }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mode.set", [request], cancellationToken); } } -/// Provides server-scoped Tools APIs. -public sealed class ServerToolsApi +/// Provides session-scoped Name APIs. +public sealed class NameApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerToolsApi(JsonRpc rpc) + internal NameApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Lists built-in tools available for a model. - /// Optional model ID — when provided, the returned tool list reflects model-specific overrides. + /// Gets the session's friendly name. /// The to monitor for cancellation requests. The default is . - /// Built-in tools available for the requested model, with their parameters and instructions. - public async Task ListAsync(string? model = null, CancellationToken cancellationToken = default) + /// The session's friendly name, or null when not yet set. + public async Task GetAsync(CancellationToken cancellationToken = default) { - var request = new ToolsListRequest { Model = model }; - return await CopilotClient.InvokeRpcAsync(_rpc, "tools.list", [request], cancellationToken); - } -} + _session.ThrowIfDisposed(); -/// Provides server-scoped Account APIs. -public sealed class ServerAccountApi -{ - private readonly JsonRpc _rpc; + var request = new SessionNameGetRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.name.get", [request], cancellationToken); + } - internal ServerAccountApi(JsonRpc rpc) + /// Sets the session's friendly name. + /// New session name (1–100 characters, trimmed of leading/trailing whitespace). + /// The to monitor for cancellation requests. The default is . + public async Task SetAsync(string name, CancellationToken cancellationToken = default) { - _rpc = rpc; + ArgumentNullException.ThrowIfNull(name); + _session.ThrowIfDisposed(); + + var request = new NameSetRequest { SessionId = _session.SessionId, Name = name }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.name.set", [request], cancellationToken); } - /// Gets Copilot quota usage for the authenticated user or supplied GitHub token. - /// GitHub token for per-user quota lookup. When provided, resolves this token to determine the user's quota instead of using the global auth. + /// Persists an auto-generated session summary as the session's name when no user-set name exists. + /// Auto-generated session summary. Empty/whitespace-only values are ignored; values are trimmed before persisting. /// The to monitor for cancellation requests. The default is . - /// Quota usage snapshots for the resolved user, keyed by quota type. - public async Task GetQuotaAsync(string? gitHubToken = null, CancellationToken cancellationToken = default) + /// Indicates whether the auto-generated summary was applied as the session's name. + public async Task SetAutoAsync(string summary, CancellationToken cancellationToken = default) { - var request = new AccountGetQuotaRequest { GitHubToken = gitHubToken }; - return await CopilotClient.InvokeRpcAsync(_rpc, "account.getQuota", [request], cancellationToken); + ArgumentNullException.ThrowIfNull(summary); + _session.ThrowIfDisposed(); + + var request = new NameSetAutoRequest { SessionId = _session.SessionId, Summary = summary }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.name.setAuto", [request], cancellationToken); } } -/// Provides server-scoped Mcp APIs. -public sealed class ServerMcpApi +/// Provides session-scoped Plan APIs. +public sealed class PlanApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerMcpApi(JsonRpc rpc) + internal PlanApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Discovers MCP servers from user, workspace, plugin, and builtin sources. - /// Working directory used as context for discovery (e.g., plugin resolution). + /// Reads the session plan file from the workspace. /// The to monitor for cancellation requests. The default is . - /// MCP servers discovered from user, workspace, plugin, and built-in sources. - public async Task DiscoverAsync(string? workingDirectory = null, CancellationToken cancellationToken = default) + /// Existence, contents, and resolved path of the session plan file. + public async Task ReadAsync(CancellationToken cancellationToken = default) { - var request = new McpDiscoverRequest { WorkingDirectory = workingDirectory }; - return await CopilotClient.InvokeRpcAsync(_rpc, "mcp.discover", [request], cancellationToken); + _session.ThrowIfDisposed(); + + var request = new SessionPlanReadRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.read", [request], cancellationToken); } - /// Config APIs. - public ServerMcpConfigApi Config => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + /// Writes new content to the session plan file. + /// The new content for the plan file. + /// The to monitor for cancellation requests. The default is . + public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(content); + _session.ThrowIfDisposed(); + + var request = new PlanUpdateRequest { SessionId = _session.SessionId, Content = content }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.update", [request], cancellationToken); + } + + /// Deletes the session plan file from the workspace. + /// The to monitor for cancellation requests. The default is . + public async Task DeleteAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionPlanDeleteRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.delete", [request], cancellationToken); + } } -/// Provides server-scoped McpConfig APIs. -public sealed class ServerMcpConfigApi +/// Provides session-scoped Workspaces APIs. +public sealed class WorkspacesApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerMcpConfigApi(JsonRpc rpc) + internal WorkspacesApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Lists MCP servers from user configuration. + /// Gets current workspace metadata for the session. /// The to monitor for cancellation requests. The default is . - /// User-configured MCP servers, keyed by server name. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// Current workspace metadata for the session, including its absolute filesystem path when available. + public async Task GetWorkspaceAsync(CancellationToken cancellationToken = default) { - return await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.list", [], cancellationToken); + _session.ThrowIfDisposed(); + + var request = new SessionWorkspacesGetWorkspaceRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.getWorkspace", [request], cancellationToken); } - /// Adds an MCP server to user configuration. - /// Unique name for the MCP server. - /// MCP server configuration (stdio process or remote HTTP/SSE). + /// Lists files stored in the session workspace files directory. /// The to monitor for cancellation requests. The default is . - public async Task AddAsync(string name, object config, CancellationToken cancellationToken = default) + /// Relative paths of files stored in the session workspace files directory. + public async Task ListFilesAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); - ArgumentNullException.ThrowIfNull(config); + _session.ThrowIfDisposed(); - var request = new McpConfigAddRequest { Name = name, Config = config }; - await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.add", [request], cancellationToken); + var request = new SessionWorkspacesListFilesRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.listFiles", [request], cancellationToken); } - /// Updates an MCP server in user configuration. - /// Name of the MCP server to update. - /// MCP server configuration (stdio process or remote HTTP/SSE). + /// Reads a file from the session workspace files directory. + /// Relative path within the workspace files directory. /// The to monitor for cancellation requests. The default is . - public async Task UpdateAsync(string name, object config, CancellationToken cancellationToken = default) + /// Contents of the requested workspace file as a UTF-8 string. + public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); - ArgumentNullException.ThrowIfNull(config); + ArgumentNullException.ThrowIfNull(path); + _session.ThrowIfDisposed(); - var request = new McpConfigUpdateRequest { Name = name, Config = config }; - await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.update", [request], cancellationToken); + var request = new WorkspacesReadFileRequest { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.readFile", [request], cancellationToken); } - /// Removes an MCP server from user configuration. - /// Name of the MCP server to remove. + /// Creates or overwrites a file in the session workspace files directory. + /// Relative path within the workspace files directory. + /// File content to write as a UTF-8 string. /// The to monitor for cancellation requests. The default is . - public async Task RemoveAsync(string name, CancellationToken cancellationToken = default) + public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(path); + ArgumentNullException.ThrowIfNull(content); + _session.ThrowIfDisposed(); - var request = new McpConfigRemoveRequest { Name = name }; - await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.remove", [request], cancellationToken); + var request = new WorkspacesCreateFileRequest { SessionId = _session.SessionId, Path = path, Content = content }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.createFile", [request], cancellationToken); } - /// Enables MCP servers in user configuration for new sessions. - /// Names of MCP servers to enable. Each server is removed from the persisted disabled list so new sessions spawn it. Unknown or already-enabled names are ignored. + /// Lists workspace checkpoints in chronological order. /// The to monitor for cancellation requests. The default is . - public async Task EnableAsync(IList names, CancellationToken cancellationToken = default) + /// Workspace checkpoints in chronological order; empty when the workspace is not enabled. + public async Task ListCheckpointsAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(names); + _session.ThrowIfDisposed(); - var request = new McpConfigEnableRequest { Names = names }; - await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.enable", [request], cancellationToken); + var request = new SessionWorkspacesListCheckpointsRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.listCheckpoints", [request], cancellationToken); } - /// Disables MCP servers in user configuration for new sessions. - /// Names of MCP servers to disable. Each server is added to the persisted disabled list so new sessions skip it. Already-disabled names are ignored. Active sessions keep their current connections until they end. + /// Reads the content of a workspace checkpoint by number. + /// Checkpoint number to read. /// The to monitor for cancellation requests. The default is . - public async Task DisableAsync(IList names, CancellationToken cancellationToken = default) + /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. + public async Task ReadCheckpointAsync(long number, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(names); - - var request = new McpConfigDisableRequest { Names = names }; - await CopilotClient.InvokeRpcAsync(_rpc, "mcp.config.disable", [request], cancellationToken); - } -} - -/// Provides server-scoped Skills APIs. -public sealed class ServerSkillsApi -{ - private readonly JsonRpc _rpc; + _session.ThrowIfDisposed(); - internal ServerSkillsApi(JsonRpc rpc) - { - _rpc = rpc; + var request = new WorkspacesReadCheckpointRequest { SessionId = _session.SessionId, Number = number }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.readCheckpoint", [request], cancellationToken); } - /// Discovers skills across global and project sources. - /// Optional list of project directory paths to scan for project-scoped skills. - /// Optional list of additional skill directory paths to include. + /// Saves pasted content as a UTF-8 file in the session workspace. + /// Pasted content to save as a UTF-8 file. /// The to monitor for cancellation requests. The default is . - /// Skills discovered across global and project sources. - public async Task DiscoverAsync(IList? projectPaths = null, IList? skillDirectories = null, CancellationToken cancellationToken = default) + /// Descriptor for the saved paste file, or null when the workspace is unavailable. + public async Task SaveLargePasteAsync(string content, CancellationToken cancellationToken = default) { - var request = new SkillsDiscoverRequest { ProjectPaths = projectPaths, SkillDirectories = skillDirectories }; - return await CopilotClient.InvokeRpcAsync(_rpc, "skills.discover", [request], cancellationToken); - } + ArgumentNullException.ThrowIfNull(content); + _session.ThrowIfDisposed(); - /// Config APIs. - public ServerSkillsConfigApi Config => - field ?? - Interlocked.CompareExchange(ref field, new(_rpc), null) ?? - field; + var request = new WorkspacesSaveLargePasteRequest { SessionId = _session.SessionId, Content = content }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.saveLargePaste", [request], cancellationToken); + } } -/// Provides server-scoped SkillsConfig APIs. -public sealed class ServerSkillsConfigApi +/// Provides session-scoped Instructions APIs. +public sealed class InstructionsApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerSkillsConfigApi(JsonRpc rpc) + internal InstructionsApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Replaces the global list of disabled skills. - /// List of skill names to disable. + /// Gets instruction sources loaded for the session. /// The to monitor for cancellation requests. The default is . - public async Task SetDisabledSkillsAsync(IList disabledSkills, CancellationToken cancellationToken = default) + /// Instruction sources loaded for the session, in merge order. + public async Task GetSourcesAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(disabledSkills); + _session.ThrowIfDisposed(); - var request = new SkillsConfigSetDisabledSkillsRequest { DisabledSkills = disabledSkills }; - await CopilotClient.InvokeRpcAsync(_rpc, "skills.config.setDisabledSkills", [request], cancellationToken); + var request = new SessionInstructionsGetSourcesRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.instructions.getSources", [request], cancellationToken); } } -/// Provides server-scoped SessionFs APIs. -public sealed class ServerSessionFsApi +/// Provides session-scoped Fleet APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class FleetApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerSessionFsApi(JsonRpc rpc) + internal FleetApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Registers an SDK client as the session filesystem provider. - /// Initial working directory for sessions. - /// Path within each session's SessionFs where the runtime stores files for that session. - /// Path conventions used by this filesystem. - /// Optional capabilities declared by the provider. + /// Starts fleet mode by submitting the fleet orchestration prompt to the session. + /// Optional user prompt to combine with fleet instructions. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the calling client was registered as the session filesystem provider. - public async Task SetProviderAsync(string initialCwd, string sessionStatePath, SessionFsSetProviderConventions conventions, SessionFsSetProviderCapabilities? capabilities = null, CancellationToken cancellationToken = default) + /// Indicates whether fleet mode was successfully activated. + public async Task StartAsync(string? prompt = null, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(initialCwd); - ArgumentNullException.ThrowIfNull(sessionStatePath); + _session.ThrowIfDisposed(); - var request = new SessionFsSetProviderRequest { InitialCwd = initialCwd, SessionStatePath = sessionStatePath, Conventions = conventions, Capabilities = capabilities }; - return await CopilotClient.InvokeRpcAsync(_rpc, "sessionFs.setProvider", [request], cancellationToken); + var request = new FleetStartRequest { SessionId = _session.SessionId, Prompt = prompt }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.fleet.start", [request], cancellationToken); } } -/// Provides server-scoped Sessions APIs. +/// Provides session-scoped Agent APIs. [Experimental(Diagnostics.Experimental)] -public sealed class ServerSessionsApi +public sealed class AgentApi { - private readonly JsonRpc _rpc; + private readonly CopilotSession _session; - internal ServerSessionsApi(JsonRpc rpc) + internal AgentApi(CopilotSession session) { - _rpc = rpc; + _session = session; } - /// Creates a new session by forking persisted history from an existing session. - /// Source session ID to fork from. - /// Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. - /// Optional friendly name to assign to the forked session. + /// Lists custom agents available to the session. /// The to monitor for cancellation requests. The default is . - /// Identifier and optional friendly name assigned to the newly forked session. - public async Task ForkAsync(string sessionId, string? toEventId = null, string? name = null, CancellationToken cancellationToken = default) + /// Custom agents available to the session. + public async Task ListAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(sessionId); + _session.ThrowIfDisposed(); - var request = new SessionsForkRequest { SessionId = sessionId, ToEventId = toEventId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.fork", [request], cancellationToken); + var request = new SessionAgentListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.list", [request], cancellationToken); } - /// Connects to an existing remote session and exposes it as an SDK session. - /// Session ID to connect to. + /// Gets the currently selected custom agent for the session. /// The to monitor for cancellation requests. The default is . - /// Remote session connection result. - public async Task ConnectAsync(string sessionId, CancellationToken cancellationToken = default) + /// The currently selected custom agent, or null when using the default agent. + public async Task GetCurrentAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(sessionId); + _session.ThrowIfDisposed(); - var request = new ConnectRemoteSessionParams { SessionId = sessionId }; - return await CopilotClient.InvokeRpcAsync(_rpc, "sessions.connect", [request], cancellationToken); + var request = new SessionAgentGetCurrentRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.getCurrent", [request], cancellationToken); } -} - -/// Provides typed session-scoped RPC methods. -public sealed class SessionRpc -{ - private readonly CopilotSession _session; - internal SessionRpc(CopilotSession session) + /// Selects a custom agent for subsequent turns in the session. + /// Name of the custom agent to select. + /// The to monitor for cancellation requests. The default is . + /// The newly selected custom agent. + public async Task SelectAsync(string name, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(name); + _session.ThrowIfDisposed(); + + var request = new AgentSelectRequest { SessionId = _session.SessionId, Name = name }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.select", [request], cancellationToken); } - internal CopilotSession Session => _session; + /// Clears the selected custom agent and returns the session to the default agent. + /// The to monitor for cancellation requests. The default is . + public async Task DeselectAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Auth APIs. - public AuthApi Auth => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionAgentDeselectRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.deselect", [request], cancellationToken); + } - /// Model APIs. - public ModelApi Model => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Reloads custom agent definitions and returns the refreshed list. + /// The to monitor for cancellation requests. The default is . + /// Custom agents available to the session after reloading definitions from disk. + public async Task ReloadAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Mode APIs. - public ModeApi Mode => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionAgentReloadRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.reload", [request], cancellationToken); + } +} + +/// Provides session-scoped Tasks APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class TasksApi +{ + private readonly CopilotSession _session; - /// Name APIs. - public NameApi Name => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + internal TasksApi(CopilotSession session) + { + _session = session; + } - /// Plan APIs. - public PlanApi Plan => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Starts a background agent task in the session. + /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose'). + /// Task prompt for the agent. + /// Short name for the agent, used to generate a human-readable ID. + /// Short description of the task. + /// Optional model override. + /// The to monitor for cancellation requests. The default is . + /// Identifier assigned to the newly started background agent task. + public async Task StartAgentAsync(string agentType, string prompt, string name, string? description = null, string? model = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(agentType); + ArgumentNullException.ThrowIfNull(prompt); + ArgumentNullException.ThrowIfNull(name); + _session.ThrowIfDisposed(); - /// Workspaces APIs. - public WorkspacesApi Workspaces => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new TasksStartAgentRequest { SessionId = _session.SessionId, AgentType = agentType, Prompt = prompt, Name = name, Description = description, Model = model }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.startAgent", [request], cancellationToken); + } - /// Instructions APIs. - public InstructionsApi Instructions => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Lists background tasks tracked by the session. + /// The to monitor for cancellation requests. The default is . + /// Background tasks currently tracked by the session. + public async Task ListAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Fleet APIs. - public FleetApi Fleet => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionTasksListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.list", [request], cancellationToken); + } - /// Agent APIs. - public AgentApi Agent => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Refreshes metadata for any detached background shells the runtime knows about. + /// The to monitor for cancellation requests. The default is . + /// Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. + public async Task RefreshAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Tasks APIs. - public TasksApi Tasks => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionTasksRefreshRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.refresh", [request], cancellationToken); + } - /// Skills APIs. - public SkillsApi Skills => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Waits for all in-flight background tasks and any follow-up turns to settle. + /// The to monitor for cancellation requests. The default is . + /// Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). + public async Task WaitForPendingAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Mcp APIs. - public McpApi Mcp => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionTasksWaitForPendingRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.waitForPending", [request], cancellationToken); + } - /// Plugins APIs. - public PluginsApi Plugins => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Returns progress information for a background task by ID. + /// Task identifier (agent ID or shell ID). + /// The to monitor for cancellation requests. The default is . + /// Progress information for the task, or null when no task with that ID is tracked. + public async Task GetProgressAsync(string id, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(id); + _session.ThrowIfDisposed(); - /// Extensions APIs. - public ExtensionsApi Extensions => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new TasksGetProgressRequest { SessionId = _session.SessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.getProgress", [request], cancellationToken); + } - /// Tools APIs. - public ToolsApi Tools => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Returns the first sync-waiting task that can currently be promoted to background mode. + /// The to monitor for cancellation requests. The default is . + /// The first sync-waiting task that can currently be promoted to background mode. + public async Task GetCurrentPromotableAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// Commands APIs. - public CommandsApi Commands => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionTasksGetCurrentPromotableRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.getCurrentPromotable", [request], cancellationToken); + } - /// Ui APIs. - public UiApi Ui => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Promotes an eligible synchronously-waited task so it continues running in the background. + /// Task identifier. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the task was successfully promoted to background mode. + public async Task PromoteToBackgroundAsync(string id, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(id); + _session.ThrowIfDisposed(); - /// Permissions APIs. - public PermissionsApi Permissions => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new TasksPromoteToBackgroundRequest { SessionId = _session.SessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.promoteToBackground", [request], cancellationToken); + } - /// Shell APIs. - public ShellApi Shell => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Atomically promotes the first promotable sync-waiting task to background mode and returns it. + /// The to monitor for cancellation requests. The default is . + /// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. + public async Task PromoteCurrentToBackgroundAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - /// History APIs. - public HistoryApi History => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new SessionTasksPromoteCurrentToBackgroundRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.promoteCurrentToBackground", [request], cancellationToken); + } - /// Usage APIs. - public UsageApi Usage => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + /// Cancels a background task. + /// Task identifier. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the background task was successfully cancelled. + public async Task CancelAsync(string id, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(id); + _session.ThrowIfDisposed(); - /// Remote APIs. - public RemoteApi Remote => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; + var request = new TasksCancelRequest { SessionId = _session.SessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.cancel", [request], cancellationToken); + } - /// Suspends the session while preserving persisted state for later resume. + /// Removes a completed or cancelled background task from tracking. + /// Task identifier. /// The to monitor for cancellation requests. The default is . - public async Task SuspendAsync(CancellationToken cancellationToken = default) + /// Indicates whether the task was removed. False when the task does not exist or is still running/idle. + public async Task RemoveAsync(string id, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(id); _session.ThrowIfDisposed(); - var request = new SessionSuspendRequest { SessionId = _session.SessionId }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.suspend", [request], cancellationToken); + var request = new TasksRemoveRequest { SessionId = _session.SessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.remove", [request], cancellationToken); } - /// Emits a user-visible session log event. - /// Human-readable message. - /// Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". - /// When true, the message is transient and not persisted to the session event log on disk. - /// Optional URL the user can open in their browser for more details. + /// Sends a message to a background agent task. + /// Agent task identifier. + /// Message content to send to the agent. + /// Agent ID of the sender, if sent on behalf of another agent. /// The to monitor for cancellation requests. The default is . - /// Identifier of the session event that was emitted for the log message. - public async Task LogAsync(string message, SessionLogLevel? level = null, bool? ephemeral = null, string? url = null, CancellationToken cancellationToken = default) + /// Indicates whether the message was delivered, with an error message when delivery failed. + public async Task SendMessageAsync(string id, string message, string? fromAgentId = null, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(id); ArgumentNullException.ThrowIfNull(message); _session.ThrowIfDisposed(); - var request = new LogRequest { SessionId = _session.SessionId, Message = message, Level = level, Ephemeral = ephemeral, Url = url }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.log", [request], cancellationToken); + var request = new TasksSendMessageRequest { SessionId = _session.SessionId, Id = id, Message = message, FromAgentId = fromAgentId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.sendMessage", [request], cancellationToken); } } -/// Provides session-scoped Auth APIs. -public sealed class AuthApi +/// Provides session-scoped Skills APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class SkillsApi { private readonly CopilotSession _session; - internal AuthApi(CopilotSession session) + internal SkillsApi(CopilotSession session) { _session = session; } - /// Gets authentication status and account metadata for the session. + /// Lists skills available to the session. /// The to monitor for cancellation requests. The default is . - /// Authentication status and account metadata for the session. - public async Task GetStatusAsync(CancellationToken cancellationToken = default) + /// Skills available to the session, with their enabled state. + public async Task ListAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionAuthGetStatusRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.auth.getStatus", [request], cancellationToken); + var request = new SessionSkillsListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.list", [request], cancellationToken); } -} -/// Provides session-scoped Model APIs. -public sealed class ModelApi -{ - private readonly CopilotSession _session; + /// Returns the skills that have been invoked during this session. + /// The to monitor for cancellation requests. The default is . + /// Skills invoked during this session, ordered by invocation time (most recent last). + public async Task GetInvokedAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); - internal ModelApi(CopilotSession session) + var request = new SessionSkillsGetInvokedRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.getInvoked", [request], cancellationToken); + } + + /// Enables a skill for the session. + /// Name of the skill to enable. + /// The to monitor for cancellation requests. The default is . + public async Task EnableAsync(string name, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(name); + _session.ThrowIfDisposed(); + + var request = new SkillsEnableRequest { SessionId = _session.SessionId, Name = name }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.enable", [request], cancellationToken); } - /// Gets the currently selected model for the session. + /// Disables a skill for the session. + /// Name of the skill to disable. /// The to monitor for cancellation requests. The default is . - /// The currently selected model for the session. - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task DisableAsync(string name, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(name); _session.ThrowIfDisposed(); - var request = new SessionModelGetCurrentRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.model.getCurrent", [request], cancellationToken); + var request = new SkillsDisableRequest { SessionId = _session.SessionId, Name = name }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.disable", [request], cancellationToken); + } + + /// Reloads skill definitions for the session. + /// The to monitor for cancellation requests. The default is . + /// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. + public async Task ReloadAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionSkillsReloadRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.reload", [request], cancellationToken); } - /// Switches the session to a model and optional reasoning configuration. - /// Model identifier to switch to. - /// Reasoning effort level to use for the model. "none" disables reasoning. - /// Reasoning summary mode to request for supported model clients. - /// Override individual model capabilities resolved by the runtime. + /// Ensures the session's skill definitions have been loaded from disk. /// The to monitor for cancellation requests. The default is . - /// The model identifier active on the session after the switch. - public async Task SwitchToAsync(string modelId, string? reasoningEffort = null, ReasoningSummary? reasoningSummary = null, ModelCapabilitiesOverride? modelCapabilities = null, CancellationToken cancellationToken = default) + public async Task EnsureLoadedAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(modelId); _session.ThrowIfDisposed(); - var request = new ModelSwitchToRequest { SessionId = _session.SessionId, ModelId = modelId, ReasoningEffort = reasoningEffort, ReasoningSummary = reasoningSummary, ModelCapabilities = modelCapabilities }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.model.switchTo", [request], cancellationToken); + var request = new SessionSkillsEnsureLoadedRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.ensureLoaded", [request], cancellationToken); } } -/// Provides session-scoped Mode APIs. -public sealed class ModeApi +/// Provides session-scoped Mcp APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class McpApi { private readonly CopilotSession _session; - internal ModeApi(CopilotSession session) + internal McpApi(CopilotSession session) { _session = session; } - /// Gets the current agent interaction mode. + /// Lists MCP servers configured for the session and their connection status. /// The to monitor for cancellation requests. The default is . - /// The session mode the agent is operating in. - public async Task GetAsync(CancellationToken cancellationToken = default) + /// MCP servers configured for the session, with their connection status. + public async Task ListAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionModeGetRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mode.get", [request], cancellationToken); + var request = new SessionMcpListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.list", [request], cancellationToken); } - /// Sets the current agent interaction mode. - /// The session mode the agent is operating in. + /// Enables an MCP server for the session. + /// Name of the MCP server to enable. /// The to monitor for cancellation requests. The default is . - public async Task SetAsync(SessionMode mode, CancellationToken cancellationToken = default) + public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(serverName); _session.ThrowIfDisposed(); - var request = new ModeSetRequest { SessionId = _session.SessionId, Mode = mode }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mode.set", [request], cancellationToken); - } -} - -/// Provides session-scoped Name APIs. -public sealed class NameApi -{ - private readonly CopilotSession _session; - - internal NameApi(CopilotSession session) - { - _session = session; + var request = new McpEnableRequest { SessionId = _session.SessionId, ServerName = serverName }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.enable", [request], cancellationToken); } - /// Gets the session's friendly name. + /// Disables an MCP server for the session. + /// Name of the MCP server to disable. /// The to monitor for cancellation requests. The default is . - /// The session's friendly name, or null when not yet set. - public async Task GetAsync(CancellationToken cancellationToken = default) + public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(serverName); _session.ThrowIfDisposed(); - var request = new SessionNameGetRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.name.get", [request], cancellationToken); + var request = new McpDisableRequest { SessionId = _session.SessionId, ServerName = serverName }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.disable", [request], cancellationToken); } - /// Sets the session's friendly name. - /// New session name (1–100 characters, trimmed of leading/trailing whitespace). + /// Reloads MCP server connections for the session. /// The to monitor for cancellation requests. The default is . - public async Task SetAsync(string name, CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); _session.ThrowIfDisposed(); - var request = new NameSetRequest { SessionId = _session.SessionId, Name = name }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.name.set", [request], cancellationToken); + var request = new SessionMcpReloadRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.reload", [request], cancellationToken); } -} - -/// Provides session-scoped Plan APIs. -public sealed class PlanApi -{ - private readonly CopilotSession _session; - internal PlanApi(CopilotSession session) + /// Runs an MCP sampling inference on behalf of an MCP server. + /// Caller-provided unique identifier for this sampling execution. Use this same ID with cancelSamplingExecution to cancel the in-flight call. Must be unique within the session for the lifetime of the call. + /// Name of the MCP server that initiated the sampling request. + /// The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate the inference with the originating MCP request for telemetry; this is distinct from `requestId` (which is the schema-level cancellation handle). + /// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. + /// The to monitor for cancellation requests. The default is . + /// Outcome of an MCP sampling execution: success result, failure error, or cancellation. + public async Task ExecuteSamplingAsync(string requestId, string serverName, object mcpRequestId, McpExecuteSamplingRequest request, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(serverName); + ArgumentNullException.ThrowIfNull(mcpRequestId); + ArgumentNullException.ThrowIfNull(request); + _session.ThrowIfDisposed(); + + var rpcRequest = new McpExecuteSamplingParams { SessionId = _session.SessionId, RequestId = requestId, ServerName = serverName, McpRequestId = mcpRequestId, Request = request }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.executeSampling", [rpcRequest], cancellationToken); } - /// Reads the session plan file from the workspace. + /// Cancels an in-flight MCP sampling execution by request ID. + /// The requestId previously passed to executeSampling that should be cancelled. /// The to monitor for cancellation requests. The default is . - /// Existence, contents, and resolved path of the session plan file. - public async Task ReadAsync(CancellationToken cancellationToken = default) + /// Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. + public async Task CancelSamplingExecutionAsync(string requestId, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); - var request = new SessionPlanReadRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.read", [request], cancellationToken); + var request = new McpCancelSamplingExecutionParams { SessionId = _session.SessionId, RequestId = requestId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.cancelSamplingExecution", [request], cancellationToken); } - /// Writes new content to the session plan file. - /// The new content for the plan file. + /// Sets how environment-variable values supplied to MCP servers are resolved (direct or indirect). + /// How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". /// The to monitor for cancellation requests. The default is . - public async Task UpdateAsync(string content, CancellationToken cancellationToken = default) + /// Env-value mode recorded on the session after the update. + public async Task SetEnvValueModeAsync(McpSetEnvValueModeDetails mode, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(content); _session.ThrowIfDisposed(); - var request = new PlanUpdateRequest { SessionId = _session.SessionId, Content = content }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.update", [request], cancellationToken); + var request = new McpSetEnvValueModeParams { SessionId = _session.SessionId, Mode = mode }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.setEnvValueMode", [request], cancellationToken); } - /// Deletes the session plan file from the workspace. + /// Removes the auto-managed `github` MCP server when present. /// The to monitor for cancellation requests. The default is . - public async Task DeleteAsync(CancellationToken cancellationToken = default) + /// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). + public async Task RemoveGitHubAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionPlanDeleteRequest { SessionId = _session.SessionId }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plan.delete", [request], cancellationToken); + var request = new SessionMcpRemoveGitHubRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.removeGitHub", [request], cancellationToken); } + + /// Oauth APIs. + public McpOauthApi Oauth => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; } -/// Provides session-scoped Workspaces APIs. -public sealed class WorkspacesApi +/// Provides session-scoped McpOauth APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class McpOauthApi { private readonly CopilotSession _session; - internal WorkspacesApi(CopilotSession session) + internal McpOauthApi(CopilotSession session) { _session = session; } - /// Gets current workspace metadata for the session. + /// Starts OAuth authentication for a remote MCP server. + /// Name of the remote MCP server to authenticate. + /// When true, clears any cached OAuth token for the server and runs a full new authorization. Use when the user explicitly wants to switch accounts or believes their session is stuck. + /// Optional override for the OAuth client display name shown on the consent screen. Applies to newly registered dynamic clients only — existing registrations keep the name they were created with. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass their own surface-specific label so the consent screen matches the product the user sees. + /// Optional override for the body text shown on the OAuth loopback callback success page. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass surface-specific copy telling the user where to return. /// The to monitor for cancellation requests. The default is . - /// Current workspace metadata for the session, or null when not available. - public async Task GetWorkspaceAsync(CancellationToken cancellationToken = default) + /// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. + public async Task LoginAsync(string serverName, bool? forceReauth = null, string? clientName = null, string? callbackSuccessMessage = null, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(serverName); _session.ThrowIfDisposed(); - var request = new SessionWorkspacesGetWorkspaceRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.getWorkspace", [request], cancellationToken); + var request = new McpOauthLoginRequest { SessionId = _session.SessionId, ServerName = serverName, ForceReauth = forceReauth, ClientName = clientName, CallbackSuccessMessage = callbackSuccessMessage }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.oauth.login", [request], cancellationToken); } +} - /// Lists files stored in the session workspace files directory. - /// The to monitor for cancellation requests. The default is . - /// Relative paths of files stored in the session workspace files directory. - public async Task ListFilesAsync(CancellationToken cancellationToken = default) - { - _session.ThrowIfDisposed(); - - var request = new SessionWorkspacesListFilesRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.listFiles", [request], cancellationToken); - } +/// Provides session-scoped Plugins APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class PluginsApi +{ + private readonly CopilotSession _session; - /// Reads a file from the session workspace files directory. - /// Relative path within the workspace files directory. - /// The to monitor for cancellation requests. The default is . - /// Contents of the requested workspace file as a UTF-8 string. - public async Task ReadFileAsync(string path, CancellationToken cancellationToken = default) + internal PluginsApi(CopilotSession session) { - ArgumentNullException.ThrowIfNull(path); - _session.ThrowIfDisposed(); - - var request = new WorkspacesReadFileRequest { SessionId = _session.SessionId, Path = path }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.readFile", [request], cancellationToken); + _session = session; } - /// Creates or overwrites a file in the session workspace files directory. - /// Relative path within the workspace files directory. - /// File content to write as a UTF-8 string. + /// Lists plugins installed for the session. /// The to monitor for cancellation requests. The default is . - public async Task CreateFileAsync(string path, string content, CancellationToken cancellationToken = default) + /// Plugins installed for the session, with their enabled state and version metadata. + public async Task ListAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(path); - ArgumentNullException.ThrowIfNull(content); _session.ThrowIfDisposed(); - var request = new WorkspacesCreateFileRequest { SessionId = _session.SessionId, Path = path, Content = content }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.workspaces.createFile", [request], cancellationToken); + var request = new SessionPluginsListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plugins.list", [request], cancellationToken); } } -/// Provides session-scoped Instructions APIs. -public sealed class InstructionsApi +/// Provides session-scoped Options APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class OptionsApi { private readonly CopilotSession _session; - internal InstructionsApi(CopilotSession session) + internal OptionsApi(CopilotSession session) { _session = session; } - /// Gets instruction sources loaded for the session. + /// Patches the genuinely-mutable subset of session options. + /// The model ID to use for assistant turns. + /// Reasoning effort for the selected model (model-defined enum). + /// Identifier of the client driving the session. + /// Identifier sent to LSP-style integrations. + /// Stable integration identifier used for analytics and rate-limit attribution. + /// Map of feature-flag IDs to their boolean enabled state. + /// Whether experimental capabilities are enabled. + /// Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the runtime. + /// Absolute working-directory path for shell tools. + /// Allowlist of tool names available to this session. + /// Denylist of tool names for this session. + /// Whether shell-script safety heuristics are enabled. + /// Shell init profile (`None` or `NonInteractive`). + /// Per-shell process flags (e.g., `pwsh` arguments). + /// Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. + /// Whether interactive shell sessions are logged. + /// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). + /// Additional directories to search for skills. + /// Skill IDs that should be excluded from this session. + /// Whether to discover custom instructions on demand after successful file views (AGENTS.md / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. + /// Full set of installed plugins for the session. Replaces the existing list; the runtime invalidates the skills cache only when the list materially changes. + /// Whether to default custom agents to local-only execution. + /// Whether to skip loading custom instruction sources. + /// Instruction source IDs to exclude from the system prompt. + /// Whether to include the `Co-authored-by` trailer in commit messages. + /// Optional path for trajectory output. + /// Whether to stream model responses. + /// Override URL for the Copilot API endpoint. + /// Whether to disable the `ask_user` tool (encourages autonomous behavior). + /// Whether to allow auto-mode continuation across turns. + /// Whether the session is running in an interactive UI. + /// Whether to surface reasoning-summary events from the model. + /// Runtime context discriminator (e.g., `cli`, `actions`). + /// Override directory for the session-events log. When unset, the runtime's default events log directory is used. + /// Additional content-exclusion policies to merge into the session's policy set. Opaque shape; see `ContentExclusionApiResponse` in the runtime. + /// Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the per-session schedule registry; this flag only controls tool exposure (typically gated to staff users). /// The to monitor for cancellation requests. The default is . - /// Instruction sources loaded for the session, in merge order. - public async Task GetSourcesAsync(CancellationToken cancellationToken = default) + /// Indicates whether the session options patch was applied successfully. + public async Task UpdateAsync(string? model = null, string? reasoningEffort = null, string? clientName = null, string? lspClientName = null, string? integrationId = null, IDictionary? featureFlags = null, bool? isExperimentalMode = null, object? provider = null, string? workingDirectory = null, IList? availableTools = null, IList? excludedTools = null, bool? enableScriptSafety = null, string? shellInitProfile = null, IList? shellProcessFlags = null, object? sandboxConfig = null, bool? logInteractiveShells = null, OptionsUpdateEnvValueMode? envValueMode = null, IList? skillDirectories = null, IList? disabledSkills = null, bool? enableOnDemandInstructionDiscovery = null, IList? installedPlugins = null, bool? customAgentsLocalOnly = null, bool? skipCustomInstructions = null, IList? disabledInstructionSources = null, bool? coauthorEnabled = null, string? trajectoryFile = null, bool? enableStreaming = null, string? copilotUrl = null, bool? askUserDisabled = null, bool? continueOnAutoMode = null, bool? runningInInteractiveMode = null, bool? enableReasoningSummaries = null, string? agentContext = null, string? eventsLogDirectory = null, IList? additionalContentExclusionPolicies = null, bool? manageScheduleEnabled = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionInstructionsGetSourcesRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.instructions.getSources", [request], cancellationToken); + var request = new SessionUpdateOptionsParams { SessionId = _session.SessionId, Model = model, ReasoningEffort = reasoningEffort, ClientName = clientName, LspClientName = lspClientName, IntegrationId = integrationId, FeatureFlags = featureFlags, IsExperimentalMode = isExperimentalMode, Provider = provider, WorkingDirectory = workingDirectory, AvailableTools = availableTools, ExcludedTools = excludedTools, EnableScriptSafety = enableScriptSafety, ShellInitProfile = shellInitProfile, ShellProcessFlags = shellProcessFlags, SandboxConfig = sandboxConfig, LogInteractiveShells = logInteractiveShells, EnvValueMode = envValueMode, SkillDirectories = skillDirectories, DisabledSkills = disabledSkills, EnableOnDemandInstructionDiscovery = enableOnDemandInstructionDiscovery, InstalledPlugins = installedPlugins, CustomAgentsLocalOnly = customAgentsLocalOnly, SkipCustomInstructions = skipCustomInstructions, DisabledInstructionSources = disabledInstructionSources, CoauthorEnabled = coauthorEnabled, TrajectoryFile = trajectoryFile, EnableStreaming = enableStreaming, CopilotUrl = copilotUrl, AskUserDisabled = askUserDisabled, ContinueOnAutoMode = continueOnAutoMode, RunningInInteractiveMode = runningInInteractiveMode, EnableReasoningSummaries = enableReasoningSummaries, AgentContext = agentContext, EventsLogDirectory = eventsLogDirectory, AdditionalContentExclusionPolicies = additionalContentExclusionPolicies, ManageScheduleEnabled = manageScheduleEnabled }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.options.update", [request], cancellationToken); } } -/// Provides session-scoped Fleet APIs. +/// Provides session-scoped Lsp APIs. [Experimental(Diagnostics.Experimental)] -public sealed class FleetApi +public sealed class LspApi { private readonly CopilotSession _session; - internal FleetApi(CopilotSession session) + internal LspApi(CopilotSession session) { _session = session; } - /// Starts fleet mode by submitting the fleet orchestration prompt to the session. - /// Optional user prompt to combine with fleet instructions. + /// Loads the merged LSP configuration set for the session's working directory. + /// Working directory used to load project-level LSP configs. Defaults to the session working directory when omitted. + /// Git root used as the boundary when traversing for project-level LSP configs (supports monorepos). + /// Force re-initialization even when LSP configs were already loaded for the working directory. /// The to monitor for cancellation requests. The default is . - /// Indicates whether fleet mode was successfully activated. - public async Task StartAsync(string? prompt = null, CancellationToken cancellationToken = default) + public async Task InitializeAsync(string? workingDirectory = null, string? gitRoot = null, bool? force = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new FleetStartRequest { SessionId = _session.SessionId, Prompt = prompt }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.fleet.start", [request], cancellationToken); + var request = new LspInitializeRequest { SessionId = _session.SessionId, WorkingDirectory = workingDirectory, GitRoot = gitRoot, Force = force }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.lsp.initialize", [request], cancellationToken); } } -/// Provides session-scoped Agent APIs. +/// Provides session-scoped Extensions APIs. [Experimental(Diagnostics.Experimental)] -public sealed class AgentApi +public sealed class ExtensionsApi { private readonly CopilotSession _session; - internal AgentApi(CopilotSession session) + internal ExtensionsApi(CopilotSession session) { _session = session; } - /// Lists custom agents available to the session. + /// Lists extensions discovered for the session and their current status. /// The to monitor for cancellation requests. The default is . - /// Custom agents available to the session. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// Extensions discovered for the session, with their current status. + public async Task ListAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionAgentListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.list", [request], cancellationToken); + var request = new SessionExtensionsListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.list", [request], cancellationToken); } - /// Gets the currently selected custom agent for the session. + /// Enables an extension for the session. + /// Source-qualified extension ID to enable. /// The to monitor for cancellation requests. The default is . - /// The currently selected custom agent, or null when using the default agent. - public async Task GetCurrentAsync(CancellationToken cancellationToken = default) + public async Task EnableAsync(string id, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(id); _session.ThrowIfDisposed(); - var request = new SessionAgentGetCurrentRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.getCurrent", [request], cancellationToken); + var request = new ExtensionsEnableRequest { SessionId = _session.SessionId, Id = id }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.enable", [request], cancellationToken); } - /// Selects a custom agent for subsequent turns in the session. - /// Name of the custom agent to select. + /// Disables an extension for the session. + /// Source-qualified extension ID to disable. /// The to monitor for cancellation requests. The default is . - /// The newly selected custom agent. - public async Task SelectAsync(string name, CancellationToken cancellationToken = default) + public async Task DisableAsync(string id, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(id); _session.ThrowIfDisposed(); - var request = new AgentSelectRequest { SessionId = _session.SessionId, Name = name }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.select", [request], cancellationToken); + var request = new ExtensionsDisableRequest { SessionId = _session.SessionId, Id = id }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.disable", [request], cancellationToken); } - /// Clears the selected custom agent and returns the session to the default agent. + /// Reloads extension definitions and processes for the session. /// The to monitor for cancellation requests. The default is . - public async Task DeselectAsync(CancellationToken cancellationToken = default) + public async Task ReloadAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionAgentDeselectRequest { SessionId = _session.SessionId }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.deselect", [request], cancellationToken); + var request = new SessionExtensionsReloadRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.reload", [request], cancellationToken); + } +} + +/// Provides session-scoped Tools APIs. +public sealed class ToolsApi +{ + private readonly CopilotSession _session; + + internal ToolsApi(CopilotSession session) + { + _session = session; + } + + /// Provides the result for a pending external tool call. + /// Request ID of the pending tool call. + /// Tool call result (string or expanded result object). + /// Error message if the tool call failed. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the external tool call result was handled successfully. + public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(requestId); + _session.ThrowIfDisposed(); + + var request = new HandlePendingToolCallRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result, Error = error }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tools.handlePendingToolCall", [request], cancellationToken); } - /// Reloads custom agent definitions and returns the refreshed list. + /// Resolves, builds, and validates the runtime tool list for the session. /// The to monitor for cancellation requests. The default is . - /// Custom agents available to the session after reloading definitions from disk. - public async Task ReloadAsync(CancellationToken cancellationToken = default) + /// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. + public async Task InitializeAndValidateAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionAgentReloadRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.agent.reload", [request], cancellationToken); + var request = new SessionToolsInitializeAndValidateRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tools.initializeAndValidate", [request], cancellationToken); } } -/// Provides session-scoped Tasks APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class TasksApi +/// Provides session-scoped Commands APIs. +public sealed class CommandsApi { private readonly CopilotSession _session; - internal TasksApi(CopilotSession session) + internal CommandsApi(CopilotSession session) { _session = session; } - /// Starts a background agent task in the session. - /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose'). - /// Task prompt for the agent. - /// Short name for the agent, used to generate a human-readable ID. - /// Short description of the task. - /// Optional model override. + /// Lists slash commands available in the session. + /// Optional filters controlling which command sources to include in the listing. /// The to monitor for cancellation requests. The default is . - /// Identifier assigned to the newly started background agent task. - public async Task StartAgentAsync(string agentType, string prompt, string name, string? description = null, string? model = null, CancellationToken cancellationToken = default) + /// Slash commands available in the session, after applying any include/exclude filters. + public async Task ListAsync(CommandsListRequest? request = null, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(agentType); - ArgumentNullException.ThrowIfNull(prompt); - ArgumentNullException.ThrowIfNull(name); _session.ThrowIfDisposed(); - var request = new TasksStartAgentRequest { SessionId = _session.SessionId, AgentType = agentType, Prompt = prompt, Name = name, Description = description, Model = model }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.startAgent", [request], cancellationToken); + var rpcRequest = new CommandsListRequestWithSession { SessionId = _session.SessionId, IncludeBuiltins = request?.IncludeBuiltins, IncludeSkills = request?.IncludeSkills, IncludeClientCommands = request?.IncludeClientCommands }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.list", [rpcRequest], cancellationToken); } - /// Lists background tasks tracked by the session. + /// Invokes a slash command in the session. + /// Command name. Leading slashes are stripped and the name is matched case-insensitively. + /// Raw input after the command name. /// The to monitor for cancellation requests. The default is . - /// Background tasks currently tracked by the session. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). + public async Task InvokeAsync(string name, string? input = null, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(name); _session.ThrowIfDisposed(); - var request = new SessionTasksListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.list", [request], cancellationToken); + var request = new CommandsInvokeRequest { SessionId = _session.SessionId, Name = name, Input = input }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.invoke", [request], cancellationToken); } - /// Promotes an eligible synchronously-waited task so it continues running in the background. - /// Task identifier. + /// Reports completion of a pending client-handled slash command. + /// Request ID from the command invocation event. + /// Error message if the command handler failed. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the task was successfully promoted to background mode. - public async Task PromoteToBackgroundAsync(string id, CancellationToken cancellationToken = default) + /// Indicates whether the pending client-handled command was completed successfully. + public async Task HandlePendingCommandAsync(string requestId, string? error = null, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); + ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); - var request = new TasksPromoteToBackgroundRequest { SessionId = _session.SessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.promoteToBackground", [request], cancellationToken); + var request = new CommandsHandlePendingCommandRequest { SessionId = _session.SessionId, RequestId = requestId, Error = error }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.handlePendingCommand", [request], cancellationToken); } - /// Cancels a background task. - /// Task identifier. + /// Executes a slash command synchronously and returns any error. + /// Name of the slash command to invoke (without the leading '/'). + /// Argument string to pass to the command (empty string if none). /// The to monitor for cancellation requests. The default is . - /// Indicates whether the background task was successfully cancelled. - public async Task CancelAsync(string id, CancellationToken cancellationToken = default) + /// Error message produced while executing the command, if any. + public async Task ExecuteAsync(string commandName, string args, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); + ArgumentNullException.ThrowIfNull(commandName); + ArgumentNullException.ThrowIfNull(args); _session.ThrowIfDisposed(); - var request = new TasksCancelRequest { SessionId = _session.SessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.cancel", [request], cancellationToken); + var request = new ExecuteCommandParams { SessionId = _session.SessionId, CommandName = commandName, Args = args }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.execute", [request], cancellationToken); } - /// Removes a completed or cancelled background task from tracking. - /// Task identifier. + /// Enqueues a slash command for FIFO processing on the local session. + /// Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the task was removed. False when the task does not exist or is still running/idle. - public async Task RemoveAsync(string id, CancellationToken cancellationToken = default) + /// Indicates whether the command was accepted into the local execution queue. + public async Task EnqueueAsync(string command, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); + ArgumentNullException.ThrowIfNull(command); _session.ThrowIfDisposed(); - var request = new TasksRemoveRequest { SessionId = _session.SessionId, Id = id }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.remove", [request], cancellationToken); + var request = new EnqueueCommandParams { SessionId = _session.SessionId, Command = command }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.enqueue", [request], cancellationToken); } - /// Sends a message to a background agent task. - /// Agent task identifier. - /// Message content to send to the agent. - /// Agent ID of the sender, if sent on behalf of another agent. + /// Reports whether the host actually executed a queued command and whether to continue processing. + /// Request ID from the `command.queued` event the host is responding to. + /// Result of the queued command execution. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the message was delivered, with an error message when delivery failed. - public async Task SendMessageAsync(string id, string message, string? fromAgentId = null, CancellationToken cancellationToken = default) + /// Indicates whether the queued-command response was matched to a pending request. + public async Task RespondToQueuedCommandAsync(string requestId, QueuedCommandResult result, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); - ArgumentNullException.ThrowIfNull(message); + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(result); _session.ThrowIfDisposed(); - var request = new TasksSendMessageRequest { SessionId = _session.SessionId, Id = id, Message = message, FromAgentId = fromAgentId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tasks.sendMessage", [request], cancellationToken); + var request = new CommandsRespondToQueuedCommandRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.respondToQueuedCommand", [request], cancellationToken); } } -/// Provides session-scoped Skills APIs. +/// Provides session-scoped Telemetry APIs. [Experimental(Diagnostics.Experimental)] -public sealed class SkillsApi +public sealed class TelemetryApi { private readonly CopilotSession _session; - internal SkillsApi(CopilotSession session) + internal TelemetryApi(CopilotSession session) { _session = session; } - /// Lists skills available to the session. + /// Sets feature override key/value pairs to attach to subsequent telemetry events for the session. + /// Override key/value pairs to attach to subsequent telemetry events from this session. Replaces any previously-set overrides. /// The to monitor for cancellation requests. The default is . - /// Skills available to the session, with their enabled state. - public async Task ListAsync(CancellationToken cancellationToken = default) + public async Task SetFeatureOverridesAsync(IDictionary features, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(features); _session.ThrowIfDisposed(); - var request = new SessionSkillsListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.list", [request], cancellationToken); + var request = new TelemetrySetFeatureOverridesRequest { SessionId = _session.SessionId, Features = features }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.telemetry.setFeatureOverrides", [request], cancellationToken); } +} - /// Enables a skill for the session. - /// Name of the skill to enable. +/// Provides session-scoped Ui APIs. +public sealed class UiApi +{ + private readonly CopilotSession _session; + + internal UiApi(CopilotSession session) + { + _session = session; + } + + /// Requests structured input from a UI-capable client. + /// Message describing what information is needed from the user. + /// JSON Schema describing the form fields to present to the user. /// The to monitor for cancellation requests. The default is . - public async Task EnableAsync(string name, CancellationToken cancellationToken = default) + /// The elicitation response (accept with form values, decline, or cancel). + public async Task ElicitationAsync(string message, UIElicitationSchema requestedSchema, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(message); + ArgumentNullException.ThrowIfNull(requestedSchema); _session.ThrowIfDisposed(); - var request = new SkillsEnableRequest { SessionId = _session.SessionId, Name = name }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.enable", [request], cancellationToken); + var request = new UIElicitationRequest { SessionId = _session.SessionId, Message = message, RequestedSchema = requestedSchema }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.elicitation", [request], cancellationToken); } - /// Disables a skill for the session. - /// Name of the skill to disable. + /// Provides the user response for a pending elicitation request. + /// The unique request ID from the elicitation.requested event. + /// The elicitation response (accept with form values, decline, or cancel). /// The to monitor for cancellation requests. The default is . - public async Task DisableAsync(string name, CancellationToken cancellationToken = default) + /// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. + public async Task HandlePendingElicitationAsync(string requestId, UIElicitationResponse result, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(result); _session.ThrowIfDisposed(); - var request = new SkillsDisableRequest { SessionId = _session.SessionId, Name = name }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.disable", [request], cancellationToken); + var request = new UIHandlePendingElicitationRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); } - /// Reloads skill definitions for the session. + /// Resolves a pending `user_input.requested` event with the user's response. + /// The unique request ID from the user_input.requested event. + /// Schema for the `UIUserInputResponse` type. /// The to monitor for cancellation requests. The default is . - /// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. - public async Task ReloadAsync(CancellationToken cancellationToken = default) + /// Indicates whether the pending UI request was resolved by this call. + public async Task HandlePendingUserInputAsync(string requestId, UIUserInputResponse response, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(response); _session.ThrowIfDisposed(); - var request = new SessionSkillsReloadRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.skills.reload", [request], cancellationToken); + var request = new UIHandlePendingUserInputRequest { SessionId = _session.SessionId, RequestId = requestId, Response = response }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingUserInput", [request], cancellationToken); } -} - -/// Provides session-scoped Mcp APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class McpApi -{ - private readonly CopilotSession _session; - internal McpApi(CopilotSession session) + /// Resolves a pending `sampling.requested` event with a sampling result, or rejects it. + /// The unique request ID from the sampling.requested event. + /// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the pending UI request was resolved by this call. + public async Task HandlePendingSamplingAsync(string requestId, UIHandlePendingSamplingResponse? response = null, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(requestId); + _session.ThrowIfDisposed(); + + var request = new UIHandlePendingSamplingRequest { SessionId = _session.SessionId, RequestId = requestId, Response = response }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingSampling", [request], cancellationToken); } - /// Lists MCP servers configured for the session and their connection status. + /// Resolves a pending `auto_mode_switch.requested` event with the user's accept/decline decision. + /// The unique request ID from the auto_mode_switch.requested event. + /// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). /// The to monitor for cancellation requests. The default is . - /// MCP servers configured for the session, with their connection status. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// Indicates whether the pending UI request was resolved by this call. + public async Task HandlePendingAutoModeSwitchAsync(string requestId, UIAutoModeSwitchResponse response, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); - var request = new SessionMcpListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.list", [request], cancellationToken); + var request = new UIHandlePendingAutoModeSwitchRequest { SessionId = _session.SessionId, RequestId = requestId, Response = response }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingAutoModeSwitch", [request], cancellationToken); } - /// Enables an MCP server for the session. - /// Name of the MCP server to enable. + /// Resolves a pending `exit_plan_mode.requested` event with the user's response. + /// The unique request ID from the exit_plan_mode.requested event. + /// Schema for the `UIExitPlanModeResponse` type. /// The to monitor for cancellation requests. The default is . - public async Task EnableAsync(string serverName, CancellationToken cancellationToken = default) + /// Indicates whether the pending UI request was resolved by this call. + public async Task HandlePendingExitPlanModeAsync(string requestId, UIExitPlanModeResponse response, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(serverName); + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(response); _session.ThrowIfDisposed(); - var request = new McpEnableRequest { SessionId = _session.SessionId, ServerName = serverName }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.enable", [request], cancellationToken); + var request = new UIHandlePendingExitPlanModeRequest { SessionId = _session.SessionId, RequestId = requestId, Response = response }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingExitPlanMode", [request], cancellationToken); } - /// Disables an MCP server for the session. - /// Name of the MCP server to disable. + /// Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch. /// The to monitor for cancellation requests. The default is . - public async Task DisableAsync(string serverName, CancellationToken cancellationToken = default) + /// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). + public async Task RegisterDirectAutoModeSwitchHandlerAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(serverName); _session.ThrowIfDisposed(); - var request = new McpDisableRequest { SessionId = _session.SessionId, ServerName = serverName }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.disable", [request], cancellationToken); + var request = new SessionUiRegisterDirectAutoModeSwitchHandlerRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.registerDirectAutoModeSwitchHandler", [request], cancellationToken); } - /// Reloads MCP server connections for the session. + /// Unregisters a previously-registered in-process auto-mode-switch handler by its opaque handle. + /// Handle previously returned by `registerDirectAutoModeSwitchHandler`. /// The to monitor for cancellation requests. The default is . - public async Task ReloadAsync(CancellationToken cancellationToken = default) + /// Indicates whether the handle was active and the registration count was decremented. + public async Task UnregisterDirectAutoModeSwitchHandlerAsync(string handle, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(handle); _session.ThrowIfDisposed(); - var request = new SessionMcpReloadRequest { SessionId = _session.SessionId }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.reload", [request], cancellationToken); + var request = new UIUnregisterDirectAutoModeSwitchHandlerRequest { SessionId = _session.SessionId, Handle = handle }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.unregisterDirectAutoModeSwitchHandler", [request], cancellationToken); } - - /// Oauth APIs. - public McpOauthApi Oauth => - field ?? - Interlocked.CompareExchange(ref field, new(_session), null) ?? - field; } -/// Provides session-scoped McpOauth APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class McpOauthApi +/// Provides session-scoped Permissions APIs. +public sealed class PermissionsApi { private readonly CopilotSession _session; - internal McpOauthApi(CopilotSession session) + internal PermissionsApi(CopilotSession session) { _session = session; } - /// Starts OAuth authentication for a remote MCP server. - /// Name of the remote MCP server to authenticate. - /// When true, clears any cached OAuth token for the server and runs a full new authorization. Use when the user explicitly wants to switch accounts or believes their session is stuck. - /// Optional override for the OAuth client display name shown on the consent screen. Applies to newly registered dynamic clients only — existing registrations keep the name they were created with. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass their own surface-specific label so the consent screen matches the product the user sees. - /// Optional override for the body text shown on the OAuth loopback callback success page. When omitted, the runtime applies a neutral fallback; callers driving interactive auth should pass surface-specific copy telling the user where to return. + /// Replaces selected permission policy fields (rules, paths, URLs, exclusions, allow-all flags) on the session. + /// If specified, sets whether tool permission requests are auto-approved without prompting. Omit to leave the current value unchanged. + /// If specified, sets whether path/URL read permission requests are auto-approved. Omit to leave the current value unchanged. + /// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. + /// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. + /// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. + /// If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. /// The to monitor for cancellation requests. The default is . - /// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. - public async Task LoginAsync(string serverName, bool? forceReauth = null, string? clientName = null, string? callbackSuccessMessage = null, CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task ConfigureAsync(bool? approveAllToolPermissionRequests = null, bool? approveAllReadPermissionRequests = null, PermissionRulesSet? rules = null, PermissionPathsConfig? paths = null, PermissionUrlsConfig? urls = null, IList? additionalContentExclusionPolicies = null, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(serverName); _session.ThrowIfDisposed(); - var request = new McpOauthLoginRequest { SessionId = _session.SessionId, ServerName = serverName, ForceReauth = forceReauth, ClientName = clientName, CallbackSuccessMessage = callbackSuccessMessage }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.mcp.oauth.login", [request], cancellationToken); + var request = new PermissionsConfigureParams { SessionId = _session.SessionId, ApproveAllToolPermissionRequests = approveAllToolPermissionRequests, ApproveAllReadPermissionRequests = approveAllReadPermissionRequests, Rules = rules, Paths = paths, Urls = urls, AdditionalContentExclusionPolicies = additionalContentExclusionPolicies }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.configure", [request], cancellationToken); } -} - -/// Provides session-scoped Plugins APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class PluginsApi -{ - private readonly CopilotSession _session; - internal PluginsApi(CopilotSession session) + /// Provides a decision for a pending tool permission request. + /// Request ID of the pending permission request. + /// The client's response to the pending permission prompt. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the permission decision was applied; false when the request was already resolved. + public async Task HandlePendingPermissionRequestAsync(string requestId, PermissionDecision result, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(result); + _session.ThrowIfDisposed(); + + var request = new PermissionDecisionRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.handlePendingPermissionRequest", [request], cancellationToken); } - /// Lists plugins installed for the session. + /// Reconstructs the set of pending tool permission requests from the session's event history. /// The to monitor for cancellation requests. The default is . - /// Plugins installed for the session, with their enabled state and version metadata. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// List of pending permission requests reconstructed from event history. + public async Task PendingRequestsAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - var request = new SessionPluginsListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.plugins.list", [request], cancellationToken); + var request = new PermissionsPendingRequestsRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.pendingRequests", [request], cancellationToken); } -} - -/// Provides session-scoped Extensions APIs. -[Experimental(Diagnostics.Experimental)] -public sealed class ExtensionsApi -{ - private readonly CopilotSession _session; - internal ExtensionsApi(CopilotSession session) + /// Enables or disables automatic approval of tool permission requests for the session. + /// Whether to auto-approve all tool permission requests. + /// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the operation succeeded. + public async Task SetApproveAllAsync(bool enabled, PermissionsSetApproveAllSource? source = null, CancellationToken cancellationToken = default) { - _session = session; + _session.ThrowIfDisposed(); + + var request = new PermissionsSetApproveAllRequest { SessionId = _session.SessionId, Enabled = enabled, Source = source }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.setApproveAll", [request], cancellationToken); } - /// Lists extensions discovered for the session and their current status. + /// Adds or removes session-scoped or location-scoped permission rules. + /// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. + /// Rules to add to the scope. Applied before `remove`/`removeAll`. + /// Specific rules to remove from the scope. Ignored when `removeAll` is true. + /// When true, removes every rule currently in the scope (after any `add` is applied). Useful for clearing the location scope wholesale. /// The to monitor for cancellation requests. The default is . - /// Extensions discovered for the session, with their current status. - public async Task ListAsync(CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task ModifyRulesAsync(PermissionsModifyRulesScope scope, IList? add = null, IList? remove = null, bool? removeAll = null, CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); - - var request = new SessionExtensionsListRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.list", [request], cancellationToken); + + var request = new PermissionsModifyRulesParams { SessionId = _session.SessionId, Scope = scope, Add = add, Remove = remove, RemoveAll = removeAll }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.modifyRules", [request], cancellationToken); } - /// Enables an extension for the session. - /// Source-qualified extension ID to enable. + /// Sets whether the client wants permission prompts bridged into session events. + /// Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). /// The to monitor for cancellation requests. The default is . - public async Task EnableAsync(string id, CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task SetRequiredAsync(bool required, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); _session.ThrowIfDisposed(); - var request = new ExtensionsEnableRequest { SessionId = _session.SessionId, Id = id }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.enable", [request], cancellationToken); + var request = new PermissionsSetRequiredRequest { SessionId = _session.SessionId, Required = required }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.setRequired", [request], cancellationToken); } - /// Disables an extension for the session. - /// Source-qualified extension ID to disable. + /// Clears session-scoped tool permission approvals. /// The to monitor for cancellation requests. The default is . - public async Task DisableAsync(string id, CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task ResetSessionApprovalsAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(id); _session.ThrowIfDisposed(); - var request = new ExtensionsDisableRequest { SessionId = _session.SessionId, Id = id }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.disable", [request], cancellationToken); + var request = new PermissionsResetSessionApprovalsRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.resetSessionApprovals", [request], cancellationToken); } - /// Reloads extension definitions and processes for the session. + /// Notifies the runtime that a permission prompt UI has been shown to the user. + /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). /// The to monitor for cancellation requests. The default is . - public async Task ReloadAsync(CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task NotifyPromptShownAsync(string message, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(message); _session.ThrowIfDisposed(); - var request = new SessionExtensionsReloadRequest { SessionId = _session.SessionId }; - await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.extensions.reload", [request], cancellationToken); + var request = new PermissionPromptShownNotification { SessionId = _session.SessionId, Message = message }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.notifyPromptShown", [request], cancellationToken); } + + /// Paths APIs. + public PermissionsPathsApi Paths => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; + + /// Urls APIs. + public PermissionsUrlsApi Urls => + field ?? + Interlocked.CompareExchange(ref field, new(_session), null) ?? + field; } -/// Provides session-scoped Tools APIs. -public sealed class ToolsApi +/// Provides session-scoped PermissionsPaths APIs. +public sealed class PermissionsPathsApi { private readonly CopilotSession _session; - internal ToolsApi(CopilotSession session) + internal PermissionsPathsApi(CopilotSession session) { _session = session; } - /// Provides the result for a pending external tool call. - /// Request ID of the pending tool call. - /// Tool call result (string or expanded result object). - /// Error message if the tool call failed. + /// Returns the session's allowed directories and primary working directory. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the external tool call result was handled successfully. - public async Task HandlePendingToolCallAsync(string requestId, object? result = null, string? error = null, CancellationToken cancellationToken = default) + /// Snapshot of the session's allow-listed directories and primary working directory. + public async Task ListAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(requestId); _session.ThrowIfDisposed(); - var request = new HandlePendingToolCallRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result, Error = error }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.tools.handlePendingToolCall", [request], cancellationToken); + var request = new PermissionsPathsListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.paths.list", [request], cancellationToken); } -} - -/// Provides session-scoped Commands APIs. -public sealed class CommandsApi -{ - private readonly CopilotSession _session; - internal CommandsApi(CopilotSession session) + /// Adds a directory to the session's allow-list. + /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the operation succeeded. + public async Task AddAsync(string path, CancellationToken cancellationToken = default) { - _session = session; + ArgumentNullException.ThrowIfNull(path); + _session.ThrowIfDisposed(); + + var request = new PermissionPathsAddParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.paths.add", [request], cancellationToken); } - /// Lists slash commands available in the session. - /// Optional filters controlling which command sources to include in the listing. + /// Updates the session's primary working directory used by the permission policy. + /// Directory to set as the new primary working directory for the session's permission policy. /// The to monitor for cancellation requests. The default is . - /// Slash commands available in the session, after applying any include/exclude filters. - public async Task ListAsync(CommandsListRequest? request = null, CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task UpdatePrimaryAsync(string path, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(path); _session.ThrowIfDisposed(); - var rpcRequest = new CommandsListRequestWithSession { SessionId = _session.SessionId, IncludeBuiltins = request?.IncludeBuiltins, IncludeSkills = request?.IncludeSkills, IncludeClientCommands = request?.IncludeClientCommands }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.list", [rpcRequest], cancellationToken); + var request = new PermissionPathsUpdatePrimaryParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.paths.updatePrimary", [request], cancellationToken); } - /// Invokes a slash command in the session. - /// Command name. Leading slashes are stripped and the name is matched case-insensitively. - /// Raw input after the command name. + /// Reports whether a path falls within any of the session's allowed directories. + /// Path to check against the session's allowed directories. /// The to monitor for cancellation requests. The default is . - /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). - public async Task InvokeAsync(string name, string? input = null, CancellationToken cancellationToken = default) + /// Indicates whether the supplied path is within the session's allowed directories. + public async Task IsPathWithinAllowedDirectoriesAsync(string path, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(path); _session.ThrowIfDisposed(); - var request = new CommandsInvokeRequest { SessionId = _session.SessionId, Name = name, Input = input }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.invoke", [request], cancellationToken); + var request = new PermissionPathsAllowedCheckParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.paths.isPathWithinAllowedDirectories", [request], cancellationToken); } - /// Reports completion of a pending client-handled slash command. - /// Request ID from the command invocation event. - /// Error message if the command handler failed. + /// Reports whether a path falls within the session's workspace (primary) directory. + /// Path to check against the session workspace directory. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the pending client-handled command was completed successfully. - public async Task HandlePendingCommandAsync(string requestId, string? error = null, CancellationToken cancellationToken = default) + /// Indicates whether the supplied path is within the session's workspace directory. + public async Task IsPathWithinWorkspaceAsync(string path, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(requestId); + ArgumentNullException.ThrowIfNull(path); _session.ThrowIfDisposed(); - var request = new CommandsHandlePendingCommandRequest { SessionId = _session.SessionId, RequestId = requestId, Error = error }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.handlePendingCommand", [request], cancellationToken); + var request = new PermissionPathsWorkspaceCheckParams { SessionId = _session.SessionId, Path = path }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.paths.isPathWithinWorkspace", [request], cancellationToken); } +} - /// Responds to a queued command request from the session. - /// Request ID from the queued command event. - /// Result of the queued command execution. +/// Provides session-scoped PermissionsUrls APIs. +public sealed class PermissionsUrlsApi +{ + private readonly CopilotSession _session; + + internal PermissionsUrlsApi(CopilotSession session) + { + _session = session; + } + + /// Toggles the runtime's URL-permission policy between unrestricted and restricted modes. + /// Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the queued-command response was accepted by the session. - public async Task RespondToQueuedCommandAsync(string requestId, QueuedCommandResult result, CancellationToken cancellationToken = default) + /// Indicates whether the operation succeeded. + public async Task SetUnrestrictedModeAsync(bool enabled, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(requestId); - ArgumentNullException.ThrowIfNull(result); _session.ThrowIfDisposed(); - var request = new CommandsRespondToQueuedCommandRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.commands.respondToQueuedCommand", [request], cancellationToken); + var request = new PermissionUrlsSetUnrestrictedModeParams { SessionId = _session.SessionId, Enabled = enabled }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.urls.setUnrestrictedMode", [request], cancellationToken); } } -/// Provides session-scoped Ui APIs. -public sealed class UiApi +/// Provides session-scoped Metadata APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class MetadataApi { private readonly CopilotSession _session; - internal UiApi(CopilotSession session) + internal MetadataApi(CopilotSession session) { _session = session; } - /// Requests structured input from a UI-capable client. - /// Message describing what information is needed from the user. - /// JSON Schema describing the form fields to present to the user. + /// Returns a snapshot of the session's identifying metadata, mode, agent, and remote info. /// The to monitor for cancellation requests. The default is . - /// The elicitation response (accept with form values, decline, or cancel). - public async Task ElicitationAsync(string message, UIElicitationSchema requestedSchema, CancellationToken cancellationToken = default) + /// Point-in-time snapshot of slow-changing session identifier and state fields. + public async Task SnapshotAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(message); - ArgumentNullException.ThrowIfNull(requestedSchema); _session.ThrowIfDisposed(); - var request = new UIElicitationRequest { SessionId = _session.SessionId, Message = message, RequestedSchema = requestedSchema }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.elicitation", [request], cancellationToken); + var request = new SessionMetadataSnapshotRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.snapshot", [request], cancellationToken); } - /// Provides the user response for a pending elicitation request. - /// The unique request ID from the elicitation.requested event. - /// The elicitation response (accept with form values, decline, or cancel). + /// Reports whether the local session is currently processing user/agent messages. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. - public async Task HandlePendingElicitationAsync(string requestId, UIElicitationResponse result, CancellationToken cancellationToken = default) + /// Indicates whether the local session is currently processing a turn or background continuation. + public async Task IsProcessingAsync(CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(requestId); - ArgumentNullException.ThrowIfNull(result); _session.ThrowIfDisposed(); - var request = new UIHandlePendingElicitationRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.ui.handlePendingElicitation", [request], cancellationToken); + var request = new SessionMetadataIsProcessingRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.isProcessing", [request], cancellationToken); } -} - -/// Provides session-scoped Permissions APIs. -public sealed class PermissionsApi -{ - private readonly CopilotSession _session; - internal PermissionsApi(CopilotSession session) + /// Returns the token breakdown for the session's current context window for a given model. + /// Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. + /// Maximum output tokens allowed by the target model. Pass 0 if unknown. + /// Model identifier used for tokenization. Omit to use the session default. Used both for token counting and to compute display values. + /// The to monitor for cancellation requests. The default is . + /// Token breakdown for the session's current context window, or null if uninitialized. + public async Task ContextInfoAsync(long promptTokenLimit, long outputTokenLimit, string? selectedModel = null, CancellationToken cancellationToken = default) { - _session = session; + _session.ThrowIfDisposed(); + + var request = new MetadataContextInfoRequest { SessionId = _session.SessionId, PromptTokenLimit = promptTokenLimit, OutputTokenLimit = outputTokenLimit, SelectedModel = selectedModel }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.contextInfo", [request], cancellationToken); } - /// Provides a decision for a pending tool permission request. - /// Request ID of the pending permission request. - /// Decision to apply to a pending permission request. + /// Records a working-directory/git context change and emits a `session.context_changed` event. + /// Updated working directory and git context. Emitted as the new payload of `session.context_changed`. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the permission decision was applied; false when the request was already resolved. - public async Task HandlePendingPermissionRequestAsync(string requestId, PermissionDecision result, CancellationToken cancellationToken = default) + /// Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). + public async Task RecordContextChangeAsync(SessionWorkingDirectoryContext context, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(requestId); - ArgumentNullException.ThrowIfNull(result); + ArgumentNullException.ThrowIfNull(context); _session.ThrowIfDisposed(); - var request = new PermissionDecisionRequest { SessionId = _session.SessionId, RequestId = requestId, Result = result }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.handlePendingPermissionRequest", [request], cancellationToken); + var request = new MetadataRecordContextChangeRequest { SessionId = _session.SessionId, Context = context }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.recordContextChange", [request], cancellationToken); } - /// Enables or disables automatic approval of tool permission requests for the session. - /// Whether to auto-approve all tool permission requests. + /// Updates the session's recorded working directory. + /// Absolute path to set as the session's working directory. The runtime updates the session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) anchor to it. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the operation succeeded. - public async Task SetApproveAllAsync(bool enabled, CancellationToken cancellationToken = default) + /// Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. + public async Task SetWorkingDirectoryAsync(string workingDirectory, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(workingDirectory); _session.ThrowIfDisposed(); - var request = new PermissionsSetApproveAllRequest { SessionId = _session.SessionId, Enabled = enabled }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.setApproveAll", [request], cancellationToken); + var request = new MetadataSetWorkingDirectoryRequest { SessionId = _session.SessionId, WorkingDirectory = workingDirectory }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.setWorkingDirectory", [request], cancellationToken); } - /// Clears session-scoped tool permission approvals. + /// Re-tokenizes the session's existing messages against a model and returns aggregate token totals. + /// Model identifier used for tokenization. The runtime token-counts both chat-context and system-context messages against this model. /// The to monitor for cancellation requests. The default is . - /// Indicates whether the operation succeeded. - public async Task ResetSessionApprovalsAsync(CancellationToken cancellationToken = default) + /// Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. + public async Task RecomputeContextTokensAsync(string modelId, CancellationToken cancellationToken = default) { + ArgumentNullException.ThrowIfNull(modelId); _session.ThrowIfDisposed(); - var request = new PermissionsResetSessionApprovalsRequest { SessionId = _session.SessionId }; - return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.permissions.resetSessionApprovals", [request], cancellationToken); + var request = new MetadataRecomputeContextTokensRequest { SessionId = _session.SessionId, ModelId = modelId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.metadata.recomputeContextTokens", [request], cancellationToken); } } @@ -6356,7 +11957,7 @@ internal HistoryApi(CopilotSession session) /// Compacts the session history to reduce context usage. /// The to monitor for cancellation requests. The default is . - /// Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. + /// Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. public async Task CompactAsync(CancellationToken cancellationToken = default) { _session.ThrowIfDisposed(); @@ -6377,6 +11978,148 @@ public async Task TruncateAsync(string eventId, Cancellat var request = new HistoryTruncateRequest { SessionId = _session.SessionId, EventId = eventId }; return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.history.truncate", [request], cancellationToken); } + + /// Cancels any in-progress background compaction on a local session. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether an in-progress background compaction was cancelled. + public async Task CancelBackgroundCompactionAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionHistoryCancelBackgroundCompactionRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.history.cancelBackgroundCompaction", [request], cancellationToken); + } + + /// Aborts any in-progress manual compaction on a local session. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether an in-progress manual compaction was aborted. + public async Task AbortManualCompactionAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionHistoryAbortManualCompactionRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.history.abortManualCompaction", [request], cancellationToken); + } + + /// Produces a markdown summary of the session's conversation context for hand-off scenarios. + /// The to monitor for cancellation requests. The default is . + /// Markdown summary of the conversation context (empty when not available). + public async Task SummarizeForHandoffAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionHistorySummarizeForHandoffRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.history.summarizeForHandoff", [request], cancellationToken); + } +} + +/// Provides session-scoped Queue APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class QueueApi +{ + private readonly CopilotSession _session; + + internal QueueApi(CopilotSession session) + { + _session = session; + } + + /// Returns the local session's pending user-facing queued items and steering messages. + /// The to monitor for cancellation requests. The default is . + /// Snapshot of the session's pending queued items and immediate-steering messages. + public async Task PendingItemsAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionQueuePendingItemsRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.queue.pendingItems", [request], cancellationToken); + } + + /// Removes the most recently queued user-facing item (LIFO). + /// The to monitor for cancellation requests. The default is . + /// Indicates whether a user-facing pending item was removed. + public async Task RemoveMostRecentAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionQueueRemoveMostRecentRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.queue.removeMostRecent", [request], cancellationToken); + } + + /// Clears all pending queued items on the local session. + /// The to monitor for cancellation requests. The default is . + public async Task ClearAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionQueueClearRequest { SessionId = _session.SessionId }; + await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.queue.clear", [request], cancellationToken); + } +} + +/// Provides session-scoped EventLog APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class EventLogApi +{ + private readonly CopilotSession _session; + + internal EventLogApi(CopilotSession session) + { + _session = session; + } + + /// Reads a batch of session events from a cursor, optionally waiting for new events. + /// Opaque cursor returned by a previous read. Omit on the first call to start from the beginning of the session's persisted history. + /// Maximum number of events to return in this batch (1–1000, default 200). + /// Milliseconds to wait for new events when the cursor is at the tail of history. 0 (default) returns immediately even if no events are available. Capped at 30000ms. Ephemeral events that arrive during the wait are delivered in this batch but are NOT replayable on a subsequent read (use a non-zero waitMs in your next call to capture future ephemerals as they happen). + /// Either '*' to receive all event types, or a non-empty list of event types to receive. + /// Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. + /// The to monitor for cancellation requests. The default is . + /// Batch of session events returned by a read, with cursor and continuation metadata. + public async Task ReadAsync(string? cursor = null, int? max = null, TimeSpan? waitMs = null, object? types = null, EventsAgentScope? agentScope = null, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new EventLogReadRequest { SessionId = _session.SessionId, Cursor = cursor, Max = max, Wait = waitMs, Types = types, AgentScope = agentScope }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.eventLog.read", [request], cancellationToken); + } + + /// Returns a snapshot of the current tail cursor without consuming events. + /// The to monitor for cancellation requests. The default is . + /// Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). + public async Task TailAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionEventLogTailRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.eventLog.tail", [request], cancellationToken); + } + + /// Registers consumer interest in an event type for runtime gating purposes. + /// The event type the consumer wants the runtime to treat as 'observed' for behavior-switching gating. Some runtime code paths inspect whether any consumer is interested in a specific event type and choose a different implementation accordingly (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full interactive OAuth flow to the consumer; when no interest is registered the runtime installs a browserless fallback that silently reuses cached tokens). SDK clients that long-poll events do NOT automatically appear as listeners to these gating checks — they must explicitly call `registerInterest` for each event type they want the runtime to count as having a consumer. Multiple registrations for the same event type from the same or different consumers are tracked independently and must each be released. See: `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, `user_input.requested`, `elicitation.requested`, `command.queued`, `exit_plan_mode.requested`. + /// The to monitor for cancellation requests. The default is . + /// Opaque handle representing an event-type interest registration. + public async Task RegisterInterestAsync(string eventType, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(eventType); + _session.ThrowIfDisposed(); + + var request = new RegisterEventInterestParams { SessionId = _session.SessionId, EventType = eventType }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.eventLog.registerInterest", [request], cancellationToken); + } + + /// Releases a consumer's previously-registered interest in an event type. + /// Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown or already-released handle is a no-op (returns success). When the last outstanding handle for an event type is released, the runtime reverts to its 'no consumer' code path for that event type. + /// The to monitor for cancellation requests. The default is . + /// Indicates whether the operation succeeded. + public async Task ReleaseInterestAsync(string handle, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(handle); + _session.ThrowIfDisposed(); + + var request = new ReleaseEventInterestParams { SessionId = _session.SessionId, Handle = handle }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.eventLog.releaseInterest", [request], cancellationToken); + } } /// Provides session-scoped Usage APIs. @@ -6434,6 +12177,53 @@ public async Task DisableAsync(CancellationToken cancellationToken = default) var request = new SessionRemoteDisableRequest { SessionId = _session.SessionId }; await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.remote.disable", [request], cancellationToken); } + + /// Persists a remote-steerability change emitted by the host as a session event. + /// Whether the session now supports remote steering via GitHub. The runtime persists this as a `session.remote_steerable_changed` event so resume/replay sees the up-to-date capability. + /// The to monitor for cancellation requests. The default is . + /// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. + public async Task NotifySteerableChangedAsync(bool remoteSteerable, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new RemoteNotifySteerableChangedRequest { SessionId = _session.SessionId, RemoteSteerable = remoteSteerable }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.remote.notifySteerableChanged", [request], cancellationToken); + } +} + +/// Provides session-scoped Schedule APIs. +[Experimental(Diagnostics.Experimental)] +public sealed class ScheduleApi +{ + private readonly CopilotSession _session; + + internal ScheduleApi(CopilotSession session) + { + _session = session; + } + + /// Lists the session's currently active scheduled prompts. + /// The to monitor for cancellation requests. The default is . + /// Snapshot of the currently active recurring prompts for this session. + public async Task ListAsync(CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new SessionScheduleListRequest { SessionId = _session.SessionId }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.schedule.list", [request], cancellationToken); + } + + /// Removes a scheduled prompt by id. + /// Id of the scheduled prompt to remove. + /// The to monitor for cancellation requests. The default is . + /// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. + public async Task StopAsync(long id, CancellationToken cancellationToken = default) + { + _session.ThrowIfDisposed(); + + var request = new ScheduleStopRequest { SessionId = _session.SessionId, Id = id }; + return await CopilotClient.InvokeRpcAsync(_session.Rpc, "session.schedule.stop", [request], cancellationToken); + } } /// Handles `sessionFs` client session API methods. @@ -6602,13 +12392,227 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, FuncSchema version number for the session event format. [JsonPropertyName("version")] - public required double Version { get; set; } + public required long Version { get; set; } } /// Session resume metadata including current context and event count. @@ -1278,8 +1278,9 @@ public sealed partial class SessionResumeData public bool? ContinuePendingWork { get; set; } /// Total number of persisted events in the session at the time of resume. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventCount")] - public required double EventCount { get; set; } + public required long EventCount { get; set; } /// Reasoning effort level used for model calls, if applicable (e.g. "none", "low", "medium", "high", "xhigh", "max"). [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1351,9 +1352,10 @@ public sealed partial class SessionErrorData public string? Stack { get; set; } /// HTTP status code from the upstream request, if applicable. + [Range((double)100, (double)599)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("statusCode")] - public long? StatusCode { get; set; } + public int? StatusCode { get; set; } /// Optional URL associated with this error that the user can open in a browser. [Url] @@ -1571,44 +1573,52 @@ public sealed partial class SessionHandoffData public sealed partial class SessionTruncationData { /// Number of messages removed by truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesRemovedDuringTruncation")] - public required double MessagesRemovedDuringTruncation { get; set; } + public required long MessagesRemovedDuringTruncation { get; set; } /// Identifier of the component that performed truncation (e.g., "BasicTruncator"). [JsonPropertyName("performedBy")] public required string PerformedBy { get; set; } /// Number of conversation messages after truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("postTruncationMessagesLength")] - public required double PostTruncationMessagesLength { get; set; } + public required long PostTruncationMessagesLength { get; set; } /// Total tokens in conversation messages after truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("postTruncationTokensInMessages")] - public required double PostTruncationTokensInMessages { get; set; } + public required long PostTruncationTokensInMessages { get; set; } /// Number of conversation messages before truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("preTruncationMessagesLength")] - public required double PreTruncationMessagesLength { get; set; } + public required long PreTruncationMessagesLength { get; set; } /// Total tokens in conversation messages before truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("preTruncationTokensInMessages")] - public required double PreTruncationTokensInMessages { get; set; } + public required long PreTruncationTokensInMessages { get; set; } /// Maximum token count for the model's context window. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] - public required double TokenLimit { get; set; } + public required long TokenLimit { get; set; } /// Number of tokens removed by truncation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokensRemovedDuringTruncation")] - public required double TokensRemovedDuringTruncation { get; set; } + public required long TokensRemovedDuringTruncation { get; set; } } /// Session rewind details including target event and count of removed events. public sealed partial class SessionSnapshotRewindData { /// Number of events that were removed by the rewind. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventsRemoved")] - public required double EventsRemoved { get; set; } + public required long EventsRemoved { get; set; } /// Event ID that was rewound to; this event and all after it were removed. [JsonPropertyName("upToEventId")] @@ -1623,9 +1633,10 @@ public sealed partial class SessionShutdownData public required ShutdownCodeChanges CodeChanges { get; set; } /// Non-system message token count at shutdown. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] - public double? ConversationTokens { get; set; } + public long? ConversationTokens { get; set; } /// Model that was selected at the time of shutdown. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1633,9 +1644,10 @@ public sealed partial class SessionShutdownData public string? CurrentModel { get; set; } /// Total tokens in context window at shutdown. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("currentTokens")] - public double? CurrentTokens { get; set; } + public long? CurrentTokens { get; set; } /// Error description when shutdownType is "error". [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1647,17 +1659,19 @@ public sealed partial class SessionShutdownData public required IDictionary ModelMetrics { get; set; } /// Unix timestamp (milliseconds) when the session started. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("sessionStartTime")] - public required double SessionStartTime { get; set; } + public required long SessionStartTime { get; set; } /// Whether the session ended normally ("routine") or due to a crash/fatal error ("error"). [JsonPropertyName("shutdownType")] public required ShutdownType ShutdownType { get; set; } /// System message token count at shutdown. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] - public double? SystemTokens { get; set; } + public long? SystemTokens { get; set; } /// Session-wide per-token-type accumulated token counts. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1665,23 +1679,27 @@ public sealed partial class SessionShutdownData public IDictionary? TokenDetails { get; set; } /// Tool definitions token count at shutdown. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] - public double? ToolDefinitionsTokens { get; set; } + public long? ToolDefinitionsTokens { get; set; } /// Cumulative time spent in API calls during the session, in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("totalApiDurationMs")] public required TimeSpan TotalApiDuration { get; set; } /// Session-wide accumulated nano-AI units cost. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalNanoAiu")] - public double? TotalNanoAiu { get; set; } + public long? TotalNanoAiu { get; set; } /// Total number of premium API requests used during the session. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalPremiumRequests")] - public required double TotalPremiumRequests { get; set; } + public required long TotalPremiumRequests { get; set; } } /// Working directory and git context at session start. @@ -1731,13 +1749,15 @@ public sealed partial class SessionContextChangedData public sealed partial class SessionUsageInfoData { /// Token count from non-system messages (user, assistant, tool). + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] - public double? ConversationTokens { get; set; } + public long? ConversationTokens { get; set; } /// Current number of tokens in the context window. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("currentTokens")] - public required double CurrentTokens { get; set; } + public required long CurrentTokens { get; set; } /// Whether this is the first usage_info event emitted in this session. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1745,50 +1765,58 @@ public sealed partial class SessionUsageInfoData public bool? IsInitial { get; set; } /// Current number of messages in the conversation. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesLength")] - public required double MessagesLength { get; set; } + public required long MessagesLength { get; set; } /// Token count from system message(s). + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] - public double? SystemTokens { get; set; } + public long? SystemTokens { get; set; } /// Maximum token count for the model's context window. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] - public required double TokenLimit { get; set; } + public required long TokenLimit { get; set; } /// Token count from tool definitions. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] - public double? ToolDefinitionsTokens { get; set; } + public long? ToolDefinitionsTokens { get; set; } } /// Context window breakdown at the start of LLM-powered conversation compaction. public sealed partial class SessionCompactionStartData { /// Token count from non-system messages (user, assistant, tool) at compaction start. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] - public double? ConversationTokens { get; set; } + public long? ConversationTokens { get; set; } /// Token count from system message(s) at compaction start. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] - public double? SystemTokens { get; set; } + public long? SystemTokens { get; set; } /// Token count from tool definitions at compaction start. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] - public double? ToolDefinitionsTokens { get; set; } + public long? ToolDefinitionsTokens { get; set; } } /// Conversation compaction results including success status, metrics, and optional error details. public sealed partial class SessionCompactionCompleteData { /// Checkpoint snapshot number created for recovery. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("checkpointNumber")] - public double? CheckpointNumber { get; set; } + public long? CheckpointNumber { get; set; } /// File path where the checkpoint was stored. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1801,9 +1829,10 @@ public sealed partial class SessionCompactionCompleteData public CompactionCompleteCompactionTokensUsed? CompactionTokensUsed { get; set; } /// Token count from non-system messages (user, assistant, tool) after compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] - public double? ConversationTokens { get; set; } + public long? ConversationTokens { get; set; } /// Error message if compaction failed. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1811,24 +1840,28 @@ public sealed partial class SessionCompactionCompleteData public string? Error { get; set; } /// Number of messages removed during compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("messagesRemoved")] - public double? MessagesRemoved { get; set; } + public long? MessagesRemoved { get; set; } /// Total tokens in conversation after compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("postCompactionTokens")] - public double? PostCompactionTokens { get; set; } + public long? PostCompactionTokens { get; set; } /// Number of messages before compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("preCompactionMessagesLength")] - public double? PreCompactionMessagesLength { get; set; } + public long? PreCompactionMessagesLength { get; set; } /// Total tokens in conversation before compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("preCompactionTokens")] - public double? PreCompactionTokens { get; set; } + public long? PreCompactionTokens { get; set; } /// GitHub request tracing ID (x-github-request-id header) for the compaction LLM call. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -1845,19 +1878,22 @@ public sealed partial class SessionCompactionCompleteData public string? SummaryContent { get; set; } /// Token count from system message(s) after compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] - public double? SystemTokens { get; set; } + public long? SystemTokens { get; set; } /// Number of tokens removed during compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("tokensRemoved")] - public double? TokensRemoved { get; set; } + public long? TokensRemoved { get; set; } /// Token count from tool definitions after compaction. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] - public double? ToolDefinitionsTokens { get; set; } + public long? ToolDefinitionsTokens { get; set; } } /// Task completion notification with summary from the agent. @@ -1901,7 +1937,7 @@ public sealed partial class UserMessageData [JsonPropertyName("isAutopilotContinuation")] public bool? IsAutopilotContinuation { get; set; } - /// Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit. + /// Path-backed native document attachments that stayed on the tagged_files path flow because native upload could not read them or would exceed the request size limit. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("nativeDocumentPathFallbackPaths")] public string[]? NativeDocumentPathFallbackPaths { get; set; } @@ -1981,8 +2017,9 @@ public sealed partial class AssistantReasoningDeltaData public sealed partial class AssistantStreamingDeltaData { /// Cumulative total bytes received from the streaming response so far. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalResponseSizeBytes")] - public required double TotalResponseSizeBytes { get; set; } + public required long TotalResponseSizeBytes { get; set; } } /// Assistant response containing text content, optional tool requests, and interaction metadata. @@ -2022,9 +2059,10 @@ public sealed partial class AssistantMessageData public string? Model { get; set; } /// Actual output token count from the API response (completion_tokens), used for accurate token accounting. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] - public double? OutputTokens { get; set; } + public long? OutputTokens { get; set; } /// Tool call ID of the parent tool invocation when this event originates from a sub-agent. [EditorBrowsable(EditorBrowsableState.Never)] @@ -2118,14 +2156,16 @@ public sealed partial class AssistantUsageData public AssistantUsageApiEndpoint? ApiEndpoint { get; set; } /// Number of tokens read from prompt cache. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheReadTokens")] - public double? CacheReadTokens { get; set; } + public long? CacheReadTokens { get; set; } /// Number of tokens written to prompt cache. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheWriteTokens")] - public double? CacheWriteTokens { get; set; } + public long? CacheWriteTokens { get; set; } /// Per-request cost and usage data from the CAPI copilot_usage response field. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -2138,6 +2178,7 @@ public sealed partial class AssistantUsageData public double? Cost { get; set; } /// Duration of the API call in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("duration")] @@ -2149,11 +2190,13 @@ public sealed partial class AssistantUsageData public string? Initiator { get; set; } /// Number of input tokens consumed. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("inputTokens")] - public double? InputTokens { get; set; } + public long? InputTokens { get; set; } /// Average inter-token latency in milliseconds. Only available for streaming requests. + [Range(0, double.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("interTokenLatencyMs")] @@ -2164,9 +2207,10 @@ public sealed partial class AssistantUsageData public required string Model { get; set; } /// Number of output tokens produced. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] - public double? OutputTokens { get; set; } + public long? OutputTokens { get; set; } /// Parent tool call ID when this usage originates from a sub-agent. [EditorBrowsable(EditorBrowsableState.Never)] @@ -2191,11 +2235,13 @@ public sealed partial class AssistantUsageData public string? ReasoningEffort { get; set; } /// Number of output tokens used for reasoning (e.g., chain-of-thought). + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("reasoningTokens")] - public double? ReasoningTokens { get; set; } + public long? ReasoningTokens { get; set; } /// Time to first token in milliseconds. Only available for streaming requests. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("ttftMs")] @@ -2211,6 +2257,7 @@ public sealed partial class ModelCallFailureData public string? ApiCallId { get; set; } /// Duration of the failed API call in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2241,9 +2288,10 @@ public sealed partial class ModelCallFailureData public required ModelCallFailureSource Source { get; set; } /// HTTP status code from the failed request. + [Range((double)100, (double)599)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("statusCode")] - public long? StatusCode { get; set; } + public int? StatusCode { get; set; } } /// Turn abort information including the reason for termination. @@ -2461,6 +2509,7 @@ public sealed partial class SubagentCompletedData public required string AgentName { get; set; } /// Wall-clock duration of the sub-agent execution in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2476,14 +2525,16 @@ public sealed partial class SubagentCompletedData public required string ToolCallId { get; set; } /// Total tokens (input + output) consumed by the sub-agent. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalTokens")] - public double? TotalTokens { get; set; } + public long? TotalTokens { get; set; } /// Total number of tool calls made by the sub-agent. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalToolCalls")] - public double? TotalToolCalls { get; set; } + public long? TotalToolCalls { get; set; } } /// Sub-agent failure details including error message and agent information. @@ -2498,6 +2549,7 @@ public sealed partial class SubagentFailedData public required string AgentName { get; set; } /// Wall-clock duration of the sub-agent execution in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2517,14 +2569,16 @@ public sealed partial class SubagentFailedData public required string ToolCallId { get; set; } /// Total tokens (input + output) consumed before the sub-agent failed. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalTokens")] - public double? TotalTokens { get; set; } + public long? TotalTokens { get; set; } /// Total number of tool calls made before the sub-agent failed. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalToolCalls")] - public double? TotalToolCalls { get; set; } + public long? TotalToolCalls { get; set; } } /// Custom agent selection details including name and available tools. @@ -2945,9 +2999,11 @@ public sealed partial class AutoModeSwitchRequestedData public required string RequestId { get; set; } /// Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt. + [Range((double)0, (double)long.MaxValue)] + [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("retryAfterSeconds")] - public double? RetryAfterSeconds { get; set; } + public TimeSpan? RetryAfterSeconds { get; set; } } /// Auto mode switch completion notification. @@ -3167,12 +3223,14 @@ public sealed partial class ShutdownCodeChanges public required string[] FilesModified { get; set; } /// Total number of lines added during the session. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesAdded")] - public required double LinesAdded { get; set; } + public required long LinesAdded { get; set; } /// Total number of lines removed during the session. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesRemoved")] - public required double LinesRemoved { get; set; } + public required long LinesRemoved { get; set; } } /// Request count and cost metrics. @@ -3184,8 +3242,9 @@ public sealed partial class ShutdownModelMetricRequests public required double Cost { get; set; } /// Total number of API requests made to this model. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("count")] - public required double Count { get; set; } + public required long Count { get; set; } } /// Schema for the `ShutdownModelMetricTokenDetail` type. @@ -3193,8 +3252,9 @@ public sealed partial class ShutdownModelMetricRequests public sealed partial class ShutdownModelMetricTokenDetail { /// Accumulated token count for this token type. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] - public required double TokenCount { get; set; } + public required long TokenCount { get; set; } } /// Token usage breakdown. @@ -3202,25 +3262,30 @@ public sealed partial class ShutdownModelMetricTokenDetail public sealed partial class ShutdownModelMetricUsage { /// Total tokens read from prompt cache across all requests. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheReadTokens")] - public required double CacheReadTokens { get; set; } + public required long CacheReadTokens { get; set; } /// Total tokens written to prompt cache across all requests. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheWriteTokens")] - public required double CacheWriteTokens { get; set; } + public required long CacheWriteTokens { get; set; } /// Total input tokens consumed across all requests to this model. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputTokens")] - public required double InputTokens { get; set; } + public required long InputTokens { get; set; } /// Total output tokens produced across all requests to this model. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputTokens")] - public required double OutputTokens { get; set; } + public required long OutputTokens { get; set; } /// Total reasoning tokens produced across all requests to this model. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("reasoningTokens")] - public double? ReasoningTokens { get; set; } + public long? ReasoningTokens { get; set; } } /// Schema for the `ShutdownModelMetric` type. @@ -3237,9 +3302,10 @@ public sealed partial class ShutdownModelMetric public IDictionary? TokenDetails { get; set; } /// Accumulated nano-AI units cost for this model. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalNanoAiu")] - public double? TotalNanoAiu { get; set; } + public long? TotalNanoAiu { get; set; } /// Token usage breakdown. [JsonPropertyName("usage")] @@ -3251,8 +3317,9 @@ public sealed partial class ShutdownModelMetric public sealed partial class ShutdownTokenDetail { /// Accumulated token count for this token type. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] - public required double TokenCount { get; set; } + public required long TokenCount { get; set; } } /// Token usage detail for a single billing category. @@ -3261,15 +3328,17 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsageTo { /// Number of tokens in this billing batch. [JsonPropertyName("batchSize")] - public required double BatchSize { get; set; } + public required long BatchSize { get; set; } /// Cost per batch of tokens. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("costPerBatch")] - public required double CostPerBatch { get; set; } + public required long CostPerBatch { get; set; } /// Total token count for this entry. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] - public required double TokenCount { get; set; } + public required long TokenCount { get; set; } /// Token category (e.g., "input", "output"). [JsonPropertyName("tokenType")] @@ -3285,8 +3354,9 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsage public required CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail[] TokenDetails { get; set; } /// Total cost in nano-AI units for this request. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] - public required double TotalNanoAiu { get; set; } + public required long TotalNanoAiu { get; set; } } /// Token usage breakdown for the compaction LLM call (aligned with assistant.usage format). @@ -3294,14 +3364,16 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsage public sealed partial class CompactionCompleteCompactionTokensUsed { /// Cached input tokens reused in the compaction LLM call. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheReadTokens")] - public double? CacheReadTokens { get; set; } + public long? CacheReadTokens { get; set; } /// Tokens written to prompt cache in the compaction LLM call. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheWriteTokens")] - public double? CacheWriteTokens { get; set; } + public long? CacheWriteTokens { get; set; } /// Per-request cost and usage data from the CAPI copilot_usage response field. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3309,15 +3381,17 @@ public sealed partial class CompactionCompleteCompactionTokensUsed public CompactionCompleteCompactionTokensUsedCopilotUsage? CopilotUsage { get; set; } /// Duration of the compaction LLM call in milliseconds. + [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("duration")] public TimeSpan? Duration { get; set; } /// Input tokens consumed by the compaction LLM call. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("inputTokens")] - public double? InputTokens { get; set; } + public long? InputTokens { get; set; } /// Model identifier used for the compaction LLM call. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -3325,9 +3399,10 @@ public sealed partial class CompactionCompleteCompactionTokensUsed public string? Model { get; set; } /// Output tokens produced by the compaction LLM call. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] - public double? OutputTokens { get; set; } + public long? OutputTokens { get; set; } } /// Optional line range to scope the attachment to a specific section of the file. @@ -3336,11 +3411,11 @@ public sealed partial class UserMessageAttachmentFileLineRange { /// End line number (1-based, inclusive). [JsonPropertyName("end")] - public required double End { get; set; } + public required long End { get; set; } /// Start line number (1-based). [JsonPropertyName("start")] - public required double Start { get; set; } + public required long Start { get; set; } } /// File attachment. @@ -3387,12 +3462,14 @@ public sealed partial class UserMessageAttachmentDirectory : UserMessageAttachme public sealed partial class UserMessageAttachmentSelectionDetailsEnd { /// End character offset within the line (0-based). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] - public required double Character { get; set; } + public required long Character { get; set; } /// End line number (0-based). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] - public required double Line { get; set; } + public required long Line { get; set; } } /// Start position of the selection. @@ -3400,12 +3477,14 @@ public sealed partial class UserMessageAttachmentSelectionDetailsEnd public sealed partial class UserMessageAttachmentSelectionDetailsStart { /// Start character offset within the line (0-based). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] - public required double Character { get; set; } + public required long Character { get; set; } /// Start line number (0-based). + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] - public required double Line { get; set; } + public required long Line { get; set; } } /// Position range of the selection within the file. @@ -3456,7 +3535,7 @@ public sealed partial class UserMessageAttachmentGithubReference : UserMessageAt /// Issue, pull request, or discussion number. [JsonPropertyName("number")] - public required double Number { get; set; } + public required long Number { get; set; } /// Type of GitHub reference. [JsonPropertyName("referenceType")] @@ -3567,15 +3646,17 @@ public sealed partial class AssistantUsageCopilotUsageTokenDetail { /// Number of tokens in this billing batch. [JsonPropertyName("batchSize")] - public required double BatchSize { get; set; } + public required long BatchSize { get; set; } /// Cost per batch of tokens. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("costPerBatch")] - public required double CostPerBatch { get; set; } + public required long CostPerBatch { get; set; } /// Total token count for this entry. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] - public required double TokenCount { get; set; } + public required long TokenCount { get; set; } /// Token category (e.g., "input", "output"). [JsonPropertyName("tokenType")] @@ -3591,8 +3672,9 @@ public sealed partial class AssistantUsageCopilotUsage public required AssistantUsageCopilotUsageTokenDetail[] TokenDetails { get; set; } /// Total cost in nano-AI units for this request. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] - public required double TotalNanoAiu { get; set; } + public required long TotalNanoAiu { get; set; } } /// Schema for the `AssistantUsageQuotaSnapshot` type. @@ -3600,14 +3682,16 @@ public sealed partial class AssistantUsageCopilotUsage public sealed partial class AssistantUsageQuotaSnapshot { /// Total requests allowed by the entitlement. + [Range((double)-1, (double)long.MaxValue)] [JsonPropertyName("entitlementRequests")] - public required double EntitlementRequests { get; set; } + public required long EntitlementRequests { get; set; } /// Whether the user has an unlimited usage entitlement. [JsonPropertyName("isUnlimitedEntitlement")] public required bool IsUnlimitedEntitlement { get; set; } /// Number of requests over the entitlement limit. + [Range(0, double.MaxValue)] [JsonPropertyName("overage")] public required double Overage { get; set; } @@ -3615,7 +3699,8 @@ public sealed partial class AssistantUsageQuotaSnapshot [JsonPropertyName("overageAllowedWithExhaustedQuota")] public required bool OverageAllowedWithExhaustedQuota { get; set; } - /// Percentage of quota remaining (0.0 to 1.0). + /// Percentage of quota remaining (0 to 100). + [Range(0, 100)] [JsonPropertyName("remainingPercentage")] public required double RemainingPercentage { get; set; } @@ -3629,8 +3714,9 @@ public sealed partial class AssistantUsageQuotaSnapshot public required bool UsageAllowedWithExhaustedQuota { get; set; } /// Number of requests already consumed. + [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("usedRequests")] - public required double UsedRequests { get; set; } + public required long UsedRequests { get; set; } } /// Error details when the tool execution failed. @@ -3674,9 +3760,10 @@ public sealed partial class ToolExecutionCompleteContentTerminal : ToolExecution public string? Cwd { get; set; } /// Process exit code, if the command has completed. + [Range((double)0, (double)4294967295)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("exitCode")] - public double? ExitCode { get; set; } + public long? ExitCode { get; set; } /// Terminal/shell output text. [JsonPropertyName("text")] @@ -3771,9 +3858,10 @@ public sealed partial class ToolExecutionCompleteContentResourceLink : ToolExecu public required string Name { get; set; } /// Size of the resource in bytes. + [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("size")] - public double? Size { get; set; } + public long? Size { get; set; } /// Human-readable display title for the resource. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -4072,9 +4160,10 @@ public sealed partial class SystemNotificationShellCompleted : SystemNotificatio public string? Description { get; set; } /// Exit code of the shell command, if available. + [Range((double)0, (double)4294967295)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("exitCode")] - public double? ExitCode { get; set; } + public long? ExitCode { get; set; } /// Unique identifier of the shell session. [JsonPropertyName("shellId")] @@ -5008,7 +5097,7 @@ public sealed partial class PermissionResultCancelled : PermissionResult /// Nested data type for PermissionRule. public sealed partial class PermissionRule { - /// Optional rule argument matched against the request. + /// Argument value matched against the request, or null when the rule kind has no argument (e.g. 'read', 'write', 'memory'). [JsonPropertyName("argument")] public string? Argument { get; set; } diff --git a/go/rpc/zrpc.go b/go/rpc/zrpc.go index ac04cae44..6e607f9ca 100644 --- a/go/rpc/zrpc.go +++ b/go/rpc/zrpc.go @@ -12,6 +12,20 @@ import ( "time" ) +// Parameters for aborting the current turn +type AbortRequest struct { + // Finite reason code describing why the current turn was aborted + Reason *AbortReason `json:"reason,omitempty"` +} + +// Result of aborting the current turn +type AbortResult struct { + // Error message if the abort failed + Error *string `json:"error,omitempty"` + // Whether the abort completed successfully + Success bool `json:"success"` +} + type AccountGetQuotaRequest struct { // GitHub token for per-user quota lookup. When provided, resolves this token to determine // the user's quota instead of using the global auth. @@ -59,11 +73,29 @@ type AgentInfo struct { Description string `json:"description"` // Human-readable display name DisplayName string `json:"displayName"` + // Stable identifier for selection. For most agents this is the same as `name`; for + // plugin/builtin agents it may differ. Always populated; defaults to `name` when no + // distinct id was assigned. + ID string `json:"id"` + // MCP server configurations attached to this agent, keyed by server name. Server config + // shape mirrors the MCP `mcpServers` schema. + McpServers map[string]any `json:"mcpServers,omitempty"` + // Preferred model id for this agent. When omitted, inherits the outer agent's model. + Model *string `json:"model,omitempty"` // Unique identifier of the custom agent Name string `json:"name"` // Absolute local file path of the agent definition. Only set for file-based agents loaded // from disk; remote agents do not have a path. Path *string `json:"path,omitempty"` + // Skill names preloaded into this agent's context. Omitted means none. + Skills []string `json:"skills,omitempty"` + // Where the agent definition was loaded from + Source *AgentInfoSource `json:"source,omitempty"` + // Allowed tool names for this agent. Empty array means none; omitted means inherit defaults. + Tools []string `json:"tools,omitempty"` + // Whether the agent can be selected directly by the user. Agents marked `false` are + // subagent-only. + UserInvocable *bool `json:"userInvocable,omitempty"` } // Custom agents available to the session. @@ -97,6 +129,150 @@ type AgentSelectResult struct { Agent AgentInfo `json:"agent"` } +// The new auth credentials to install on the session. When omitted or `undefined`, the call +// is a no-op and the session's existing credentials are preserved. The runtime stores the +// value verbatim and uses it for outbound model/API requests; it does NOT re-validate or +// re-fetch the associated Copilot user response. Several variants carry secret material; +// treat this method's params as containing secrets at rest and in transit. +type AuthInfo interface { + authInfo() + Type() AuthInfoType +} + +type RawAuthInfoData struct { + Discriminator AuthInfoType + Raw json.RawMessage +} + +func (RawAuthInfoData) authInfo() {} +func (r RawAuthInfoData) Type() AuthInfoType { + return r.Discriminator +} + +// Schema for the `ApiKeyAuthInfo` type. +type APIKeyAuthInfo struct { + // The API key. Treat as a secret. + APIKey string `json:"apiKey"` + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Authentication host. + Host string `json:"host"` +} + +func (APIKeyAuthInfo) authInfo() {} +func (APIKeyAuthInfo) Type() AuthInfoType { + return AuthInfoTypeAPIKey +} + +// Schema for the `CopilotApiTokenAuthInfo` type. +type CopilotAPITokenAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Authentication host (always the public GitHub host). + Host CopilotAPITokenAuthInfoHost `json:"host"` +} + +func (CopilotAPITokenAuthInfo) authInfo() {} +func (CopilotAPITokenAuthInfo) Type() AuthInfoType { + return AuthInfoTypeCopilotAPIToken +} + +// Schema for the `EnvAuthInfo` type. +type EnvAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Name of the environment variable the token was sourced from. + EnvVar string `json:"envVar"` + // Authentication host (e.g. https://github.com or a GHES host). + Host string `json:"host"` + // User login associated with the token. Undefined for server-to-server tokens (those + // starting with `ghs_`). + Login *string `json:"login,omitempty"` + // The token value itself. Treat as a secret. + Token string `json:"token"` +} + +func (EnvAuthInfo) authInfo() {} +func (EnvAuthInfo) Type() AuthInfoType { + return AuthInfoTypeEnv +} + +// Schema for the `GhCliAuthInfo` type. +type GhCliAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Authentication host. + Host string `json:"host"` + // User login as reported by `gh auth status`. + Login string `json:"login"` + // The token returned by `gh auth token`. Treat as a secret. + Token string `json:"token"` +} + +func (GhCliAuthInfo) authInfo() {} +func (GhCliAuthInfo) Type() AuthInfoType { + return AuthInfoTypeGhCli +} + +// Schema for the `HMACAuthInfo` type. +type HMACAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // HMAC secret used to sign requests. + Hmac string `json:"hmac"` + // Authentication host. HMAC auth always targets the public GitHub host. + Host HMACAuthInfoHost `json:"host"` +} + +func (HMACAuthInfo) authInfo() {} +func (HMACAuthInfo) Type() AuthInfoType { + return AuthInfoTypeHmac +} + +// Schema for the `TokenAuthInfo` type. +type TokenAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Authentication host. + Host string `json:"host"` + // The token value itself. Treat as a secret. + Token string `json:"token"` +} + +func (TokenAuthInfo) authInfo() {} +func (TokenAuthInfo) Type() AuthInfoType { + return AuthInfoTypeToken +} + +// Schema for the `UserAuthInfo` type. +type UserAuthInfo struct { + // Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + // GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + // verbatim and does not re-fetch when set. + CopilotUser *CopilotUserResponse `json:"copilotUser,omitempty"` + // Authentication host. + Host string `json:"host"` + // OAuth user login. + Login string `json:"login"` +} + +func (UserAuthInfo) authInfo() {} +func (UserAuthInfo) Type() AuthInfoType { + return AuthInfoTypeUser +} + // Slash commands available in the session, after applying any include/exclude filters. type CommandList struct { // Commands available in this session @@ -135,18 +311,19 @@ type CommandsListRequest struct { IncludeSkills *bool `json:"includeSkills,omitempty"` } -// Queued command request ID and the result indicating whether the client handled it. +// Queued-command request ID and the result indicating whether the host executed it (and +// whether to stop processing further queued commands). type CommandsRespondToQueuedCommandRequest struct { - // Request ID from the queued command event + // Request ID from the `command.queued` event the host is responding to. RequestID string `json:"requestId"` - // Result of the queued command execution + // Result of the queued command execution. Result QueuedCommandResult `json:"result"` } -// Indicates whether the queued-command response was accepted by the session. +// Indicates whether the queued-command response was matched to a pending request. type CommandsRespondToQueuedCommandResult struct { - // Whether the response was accepted (false if the requestId was not found or already - // resolved) + // Whether a pending queued command with the given request ID was found and resolved. False + // when the request was already resolved, cancelled, or unknown. Success bool `json:"success"` } @@ -216,10 +393,116 @@ type ConnectResult struct { Version string `json:"version"` } -// The currently selected model for the session. +// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the +// GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this +// verbatim and does not re-fetch when set. +type CopilotUserResponse struct { + AccessTypeSku *string `json:"access_type_sku,omitempty"` + AnalyticsTrackingID *string `json:"analytics_tracking_id,omitempty"` + AssignedDate *string `json:"assigned_date,omitempty"` + CanSignupForLimited *bool `json:"can_signup_for_limited,omitempty"` + ChatEnabled *bool `json:"chat_enabled,omitempty"` + CliRemoteControlEnabled *bool `json:"cli_remote_control_enabled,omitempty"` + CloudSessionStorageEnabled *bool `json:"cloud_session_storage_enabled,omitempty"` + CodexAgentEnabled *bool `json:"codex_agent_enabled,omitempty"` + CopilotignoreEnabled *bool `json:"copilotignore_enabled,omitempty"` + CopilotPlan *string `json:"copilot_plan,omitempty"` + // Schema for the `CopilotUserResponseEndpoints` type. + Endpoints *CopilotUserResponseEndpoints `json:"endpoints,omitempty"` + IsMcpEnabled *bool `json:"is_mcp_enabled,omitempty"` + LimitedUserQuotas map[string]float64 `json:"limited_user_quotas,omitempty"` + LimitedUserResetDate *string `json:"limited_user_reset_date,omitempty"` + Login *string `json:"login,omitempty"` + MonthlyQuotas map[string]float64 `json:"monthly_quotas,omitempty"` + OrganizationList []CopilotUserResponseOrganizationListItem `json:"organization_list,omitempty"` + OrganizationLoginList []string `json:"organization_login_list,omitempty"` + QuotaResetDate *string `json:"quota_reset_date,omitempty"` + QuotaResetDateUtc *string `json:"quota_reset_date_utc,omitempty"` + // Schema for the `CopilotUserResponseQuotaSnapshots` type. + QuotaSnapshots *CopilotUserResponseQuotaSnapshots `json:"quota_snapshots,omitempty"` + RestrictedTelemetry *bool `json:"restricted_telemetry,omitempty"` + TokenBasedBilling *bool `json:"token_based_billing,omitempty"` +} + +// Schema for the `CopilotUserResponseEndpoints` type. +type CopilotUserResponseEndpoints struct { + API *string `json:"api,omitempty"` + OriginTracker *string `json:"origin-tracker,omitempty"` + Proxy *string `json:"proxy,omitempty"` + Telemetry *string `json:"telemetry,omitempty"` +} + +type CopilotUserResponseOrganizationListItem struct { + Login *string `json:"login,omitempty"` + Name *string `json:"name,omitempty"` +} + +// Schema for the `CopilotUserResponseQuotaSnapshots` type. +type CopilotUserResponseQuotaSnapshots struct { + // Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. + Chat *CopilotUserResponseQuotaSnapshotsChat `json:"chat,omitempty"` + // Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. + Completions *CopilotUserResponseQuotaSnapshotsCompletions `json:"completions,omitempty"` + // Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. + PremiumInteractions *CopilotUserResponseQuotaSnapshotsPremiumInteractions `json:"premium_interactions,omitempty"` +} + +// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. +type CopilotUserResponseQuotaSnapshotsChat struct { + Entitlement *float64 `json:"entitlement,omitempty"` + HasQuota *bool `json:"has_quota,omitempty"` + OverageCount *float64 `json:"overage_count,omitempty"` + OveragePermitted *bool `json:"overage_permitted,omitempty"` + PercentRemaining *float64 `json:"percent_remaining,omitempty"` + QuotaID *string `json:"quota_id,omitempty"` + QuotaRemaining *float64 `json:"quota_remaining,omitempty"` + QuotaResetAt *float64 `json:"quota_reset_at,omitempty"` + Remaining *float64 `json:"remaining,omitempty"` + TimestampUtc *string `json:"timestamp_utc,omitempty"` + TokenBasedBilling *bool `json:"token_based_billing,omitempty"` + Unlimited *bool `json:"unlimited,omitempty"` +} + +// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. +type CopilotUserResponseQuotaSnapshotsCompletions struct { + Entitlement *float64 `json:"entitlement,omitempty"` + HasQuota *bool `json:"has_quota,omitempty"` + OverageCount *float64 `json:"overage_count,omitempty"` + OveragePermitted *bool `json:"overage_permitted,omitempty"` + PercentRemaining *float64 `json:"percent_remaining,omitempty"` + QuotaID *string `json:"quota_id,omitempty"` + QuotaRemaining *float64 `json:"quota_remaining,omitempty"` + QuotaResetAt *float64 `json:"quota_reset_at,omitempty"` + Remaining *float64 `json:"remaining,omitempty"` + TimestampUtc *string `json:"timestamp_utc,omitempty"` + TokenBasedBilling *bool `json:"token_based_billing,omitempty"` + Unlimited *bool `json:"unlimited,omitempty"` +} + +// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. +type CopilotUserResponseQuotaSnapshotsPremiumInteractions struct { + Entitlement *float64 `json:"entitlement,omitempty"` + HasQuota *bool `json:"has_quota,omitempty"` + OverageCount *float64 `json:"overage_count,omitempty"` + OveragePermitted *bool `json:"overage_permitted,omitempty"` + PercentRemaining *float64 `json:"percent_remaining,omitempty"` + QuotaID *string `json:"quota_id,omitempty"` + QuotaRemaining *float64 `json:"quota_remaining,omitempty"` + QuotaResetAt *float64 `json:"quota_reset_at,omitempty"` + Remaining *float64 `json:"remaining,omitempty"` + TimestampUtc *string `json:"timestamp_utc,omitempty"` + TokenBasedBilling *bool `json:"token_based_billing,omitempty"` + Unlimited *bool `json:"unlimited,omitempty"` +} + +// The currently selected model and reasoning effort for the session. type CurrentModel struct { // Currently active model identifier ModelID *string `json:"modelId,omitempty"` + // Reasoning effort level currently applied to the active model, when one is set. Reads + // `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the + // two values are reported as a snapshot. + ReasoningEffort *string `json:"reasoningEffort,omitempty"` } // Schema for the `DiscoveredMcpServer` type. @@ -234,6 +517,110 @@ type DiscoveredMcpServer struct { Type *DiscoveredMcpServerType `json:"type,omitempty"` } +// Slash-prefixed command string to enqueue for FIFO processing. +type EnqueueCommandParams struct { + // Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO + // with any in-flight items; if the session is idle, processing kicks off immediately. + Command string `json:"command"` +} + +// Indicates whether the command was accepted into the local execution queue. +type EnqueueCommandResult struct { + // True when the command was accepted into the local execution queue. False when the call + // targets a session that does not support local command queueing (e.g. remote sessions). + Queued bool `json:"queued"` +} + +// Cursor, batch size, and optional long-poll/filter parameters for reading session events. +// Experimental: EventLogReadRequest is part of an experimental API and may change or be +// removed. +type EventLogReadRequest struct { + // Agent-scope filter: 'primary' returns only main-agent events plus events whose type + // starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns + // events from all agents (matching wildcard-subscription behavior). Default is 'all' to + // preserve wildcard semantics for catch-up callers. + AgentScope *EventsAgentScope `json:"agentScope,omitempty"` + // Opaque cursor returned by a previous read. Omit on the first call to start from the + // beginning of the session's persisted history. + Cursor *string `json:"cursor,omitempty"` + // Maximum number of events to return in this batch (1–1000, default 200). + Max *int32 `json:"max,omitempty"` + // Either '*' to receive all event types, or a non-empty list of event types to receive + Types *EventLogTypes `json:"types,omitempty"` + // Milliseconds to wait for new events when the cursor is at the tail of history. 0 + // (default) returns immediately even if no events are available. Capped at 30000ms. + // Ephemeral events that arrive during the wait are delivered in this batch but are NOT + // replayable on a subsequent read (use a non-zero waitMs in your next call to capture + // future ephemerals as they happen). + WaitMs *int32 `json:"waitMs,omitempty"` +} + +// Indicates whether the operation succeeded. +// Experimental: EventLogReleaseInterestResult is part of an experimental API and may change +// or be removed. +type EventLogReleaseInterestResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Snapshot of the current tail cursor without returning any events. Use this when a +// consumer wants to subscribe to live events going forward without first paginating through +// the entire persisted history (which would happen if `read` were called without a cursor +// on a long-lived session). +// Experimental: EventLogTailResult is part of an experimental API and may change or be +// removed. +type EventLogTailResult struct { + // Opaque cursor pointing at the current tail of the session's persisted-events history. + // Pass back to `read` to receive only events that arrive AFTER this snapshot. When the + // session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent + // to omitting the cursor on a first read). + Cursor string `json:"cursor"` +} + +// Either '*' to receive all event types, or a non-empty list of event types to receive +// Experimental: EventLogTypes is part of an experimental API and may change or be removed. +type EventLogTypes struct { + String *EventLogTypesString + StringArray []string +} + +// Batch of session events returned by a read, with cursor and continuation metadata. +// Experimental: EventsReadResult is part of an experimental API and may change or be +// removed. +type EventsReadResult struct { + // Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue + // from where this read left off. Always present, even when no events were returned. + Cursor string `json:"cursor"` + // Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor + // referred to an event that no longer exists in history (e.g. truncated or compacted away) + // and the read started from the beginning of the remaining history. + CursorStatus EventsCursorStatus `json:"cursorStatus"` + // Events are delivered in two batches per read: persisted events first (in append order), + // then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were + // empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral + // events do not interleave within a single read. + Events []SessionEvent `json:"events"` + // True when the read returned `max` events and more events are available immediately. When + // false, the next read with a non-zero `waitMs` will block until a new event arrives or the + // wait expires. + HasMore bool `json:"hasMore"` +} + +// Slash command name and argument string to execute synchronously. +type ExecuteCommandParams struct { + // Argument string to pass to the command (empty string if none). + Args string `json:"args"` + // Name of the slash command to invoke (without the leading '/'). + CommandName string `json:"commandName"` +} + +// Error message produced while executing the command, if any. +type ExecuteCommandResult struct { + // Error message produced while executing the command, if any. Omitted when the handler + // succeeded. + Error *string `json:"error,omitempty"` +} + // Schema for the `Extension` type. // Experimental: Extension is part of an experimental API and may change or be removed. type Extension struct { @@ -380,7 +767,7 @@ type ExternalToolTextResultForLlmContentResourceLink struct { // Resource name identifier Name string `json:"name"` // Size of the resource in bytes - Size *float64 `json:"size,omitempty"` + Size *int64 `json:"size,omitempty"` // Human-readable display title for the resource Title *string `json:"title,omitempty"` // URI identifying the resource @@ -397,7 +784,7 @@ type ExternalToolTextResultForLlmContentTerminal struct { // Working directory where the command was executed Cwd *string `json:"cwd,omitempty"` // Process exit code, if the command has completed - ExitCode *float64 `json:"exitCode,omitempty"` + ExitCode *int64 `json:"exitCode,omitempty"` // Terminal/shell output text Text string `json:"text"` } @@ -511,6 +898,24 @@ type HandlePendingToolCallResult struct { Success bool `json:"success"` } +// Indicates whether an in-progress manual compaction was aborted. +// Experimental: HistoryAbortManualCompactionResult is part of an experimental API and may +// change or be removed. +type HistoryAbortManualCompactionResult struct { + // Whether an in-progress manual compaction was aborted. False when no manual compaction was + // running, when its abort controller was already aborted, or when the session is remote. + Aborted bool `json:"aborted"` +} + +// Indicates whether an in-progress background compaction was cancelled. +// Experimental: HistoryCancelBackgroundCompactionResult is part of an experimental API and +// may change or be removed. +type HistoryCancelBackgroundCompactionResult struct { + // Whether an in-progress background compaction was cancelled. False when no compaction was + // running, when the session is remote, or when the underlying processor was unavailable. + Cancelled bool `json:"cancelled"` +} + // Post-compaction context window usage breakdown // Experimental: HistoryCompactContextWindow is part of an experimental API and may change // or be removed. @@ -529,8 +934,8 @@ type HistoryCompactContextWindow struct { ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } -// Compaction outcome with the number of tokens and messages removed and the resulting -// context window breakdown. +// Compaction outcome with the number of tokens and messages removed, summary text, and the +// resulting context window breakdown. // Experimental: HistoryCompactResult is part of an experimental API and may change or be // removed. type HistoryCompactResult struct { @@ -540,10 +945,22 @@ type HistoryCompactResult struct { MessagesRemoved int64 `json:"messagesRemoved"` // Whether compaction completed successfully Success bool `json:"success"` + // Summary text produced by compaction. Omitted when compaction did not produce a summary + // (e.g. failure path). + SummaryContent *string `json:"summaryContent,omitempty"` // Number of tokens freed by compaction TokensRemoved int64 `json:"tokensRemoved"` } +// Markdown summary of the conversation context (empty when not available). +// Experimental: HistorySummarizeForHandoffResult is part of an experimental API and may +// change or be removed. +type HistorySummarizeForHandoffResult struct { + // Markdown summary of the conversation context produced by an LLM. Empty string when there + // are no messages or when the session does not support local summarization. + Summary string `json:"summary"` +} + // Identifier of the event to truncate to; this event and all later events are removed. // Experimental: HistoryTruncateRequest is part of an experimental API and may change or be // removed. @@ -560,6 +977,66 @@ type HistoryTruncateResult struct { EventsRemoved int64 `json:"eventsRemoved"` } +// Schema for the `InstalledPlugin` type. +// Experimental: InstalledPlugin is part of an experimental API and may change or be removed. +type InstalledPlugin struct { + // Path where the plugin is cached locally + CachePath *string `json:"cache_path,omitempty"` + // Whether the plugin is currently enabled + Enabled bool `json:"enabled"` + // Installation timestamp + InstalledAt string `json:"installed_at"` + // Marketplace the plugin came from (empty string for direct repo installs) + Marketplace string `json:"marketplace"` + // Plugin name + Name string `json:"name"` + // Source for direct repo installs (when marketplace is empty) + Source *InstalledPluginSource `json:"source,omitempty"` + // Version installed (if available) + Version *string `json:"version,omitempty"` +} + +// Source for direct repo installs (when marketplace is empty) +// Experimental: InstalledPluginSource is part of an experimental API and may change or be +// removed. +type InstalledPluginSource struct { + InstalledPluginSourceGithub *InstalledPluginSourceGithub + InstalledPluginSourceLocal *InstalledPluginSourceLocal + InstalledPluginSourceURL *InstalledPluginSourceURL + String *string +} + +// Schema for the `InstalledPluginSourceGithub` type. +// Experimental: InstalledPluginSourceGithub is part of an experimental API and may change +// or be removed. +type InstalledPluginSourceGithub struct { + Path *string `json:"path,omitempty"` + Ref *string `json:"ref,omitempty"` + Repo string `json:"repo"` + // Constant value. Always "github". + Source InstalledPluginSourceGithubSource `json:"source"` +} + +// Schema for the `InstalledPluginSourceLocal` type. +// Experimental: InstalledPluginSourceLocal is part of an experimental API and may change or +// be removed. +type InstalledPluginSourceLocal struct { + Path string `json:"path"` + // Constant value. Always "local". + Source InstalledPluginSourceLocalSource `json:"source"` +} + +// Schema for the `InstalledPluginSourceUrl` type. +// Experimental: InstalledPluginSourceURL is part of an experimental API and may change or +// be removed. +type InstalledPluginSourceURL struct { + Path *string `json:"path,omitempty"` + Ref *string `json:"ref,omitempty"` + // Constant value. Always "url". + Source InstalledPluginSourceURLSource `json:"source"` + URL string `json:"url"` +} + // Instruction sources loaded for the session, in merge order. type InstructionsGetSourcesResult struct { // Instruction sources for the session @@ -568,10 +1045,13 @@ type InstructionsGetSourcesResult struct { // Schema for the `InstructionsSources` type. type InstructionsSources struct { - // Glob pattern from frontmatter — when set, this instruction applies only to matching files - ApplyTo *string `json:"applyTo,omitempty"` + // Glob pattern(s) from frontmatter — when set, this instruction applies only to matching + // files + ApplyTo []string `json:"applyTo,omitempty"` // Raw content of the instruction file Content string `json:"content"` + // When true, this source starts disabled and must be toggled on by the user + DefaultDisabled *bool `json:"defaultDisabled,omitempty"` // Short description (body after frontmatter) for use in instruction tables Description *string `json:"description,omitempty"` // Unique identifier for this source (used for toggling) @@ -586,7 +1066,8 @@ type InstructionsSources struct { Type InstructionsSourcesType `json:"type"` } -// Message text, optional severity level, persistence flag, and optional follow-up URL. +// Message text, optional severity level, persistence flag, optional follow-up URL, and +// optional tip. type LogRequest struct { // When true, the message is transient and not persisted to the session event log on disk Ephemeral *bool `json:"ephemeral,omitempty"` @@ -595,6 +1076,11 @@ type LogRequest struct { Level *SessionLogLevel `json:"level,omitempty"` // Human-readable message Message string `json:"message"` + // Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. + Tip *string `json:"tip,omitempty"` + // Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps + // to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". + Type *string `json:"type,omitempty"` // Optional URL the user can open in their browser for more details URL *string `json:"url,omitempty"` } @@ -605,6 +1091,40 @@ type LogResult struct { EventID string `json:"eventId"` } +// Parameters for (re)loading the merged LSP configuration set. +// Experimental: LspInitializeRequest is part of an experimental API and may change or be +// removed. +type LspInitializeRequest struct { + // Force re-initialization even when LSP configs were already loaded for the working + // directory. + Force *bool `json:"force,omitempty"` + // Git root used as the boundary when traversing for project-level LSP configs (supports + // monorepos). + GitRoot *string `json:"gitRoot,omitempty"` + // Working directory used to load project-level LSP configs. Defaults to the session working + // directory when omitted. + WorkingDirectory *string `json:"workingDirectory,omitempty"` +} + +// The requestId previously passed to executeSampling that should be cancelled. +// Experimental: McpCancelSamplingExecutionParams is part of an experimental API and may +// change or be removed. +type McpCancelSamplingExecutionParams struct { + // The requestId previously passed to executeSampling that should be cancelled + RequestID string `json:"requestId"` +} + +// Indicates whether an in-flight sampling execution with the given requestId was found and +// cancelled. +// Experimental: McpCancelSamplingExecutionResult is part of an experimental API and may +// change or be removed. +type McpCancelSamplingExecutionResult struct { + // True if an in-flight execution with the given requestId was found and signalled to + // cancel. False when no such execution is in flight (already completed, never started, or + // cancelled by another caller). + Cancelled bool `json:"cancelled"` +} + // MCP server name and configuration to add to user configuration. type McpConfigAddRequest struct { // MCP server configuration (stdio process or remote HTTP/SSE) @@ -691,6 +1211,42 @@ type McpEnableRequest struct { ServerName string `json:"serverName"` } +// Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. +// Experimental: McpExecuteSamplingParams is part of an experimental API and may change or +// be removed. +type McpExecuteSamplingParams struct { + // The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate + // the inference with the originating MCP request for telemetry; this is distinct from + // `requestId` (which is the schema-level cancellation handle). + McpRequestID any `json:"mcpRequestId"` + // Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. + // Treated as opaque at the schema layer; the runtime converts the embedded MCP messages + // into the OpenAI chat-completion shape internally. + Request McpExecuteSamplingRequest `json:"request"` + // Caller-provided unique identifier for this sampling execution. Use this same ID with + // cancelSamplingExecution to cancel the in-flight call. Must be unique within the session + // for the lifetime of the call. + RequestID string `json:"requestId"` + // Name of the MCP server that initiated the sampling request + ServerName string `json:"serverName"` +} + +// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. +// Treated as opaque at the schema layer; the runtime converts the embedded MCP messages +// into the OpenAI chat-completion shape internally. +// Experimental: McpExecuteSamplingRequest is part of an experimental API and may change or +// be removed. +type McpExecuteSamplingRequest struct { +} + +// MCP CreateMessageResult payload (with optional 'tools' extension), present when +// action='success'. Treated as opaque at the schema layer; consumers should +// construct/consume it per the MCP CreateMessageResult shape. +// Experimental: McpExecuteSamplingResult is part of an experimental API and may change or +// be removed. +type McpExecuteSamplingResult struct { +} + // Remote MCP server name and optional overrides controlling reauthentication, OAuth client // display name, and the callback success-page copy. // Experimental: McpOauthLoginRequest is part of an experimental API and may change or be @@ -727,6 +1283,33 @@ type McpOauthLoginResult struct { AuthorizationURL *string `json:"authorizationUrl,omitempty"` } +// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to +// remove). +// Experimental: McpRemoveGitHubResult is part of an experimental API and may change or be +// removed. +type McpRemoveGitHubResult struct { + // True when the auto-managed `github` MCP server was removed; false when no removal + // happened (e.g. user has explicitly configured a `github` server, or the server was not + // registered). + Removed bool `json:"removed"` +} + +// Outcome of an MCP sampling execution: success result, failure error, or cancellation. +// Experimental: McpSamplingExecutionResult is part of an experimental API and may change or +// be removed. +type McpSamplingExecutionResult struct { + // Outcome of the sampling inference. 'success' produced a response; 'failure' encountered + // an error (including agent-side rejection by content filter or criteria); 'cancelled' the + // caller cancelled this execution via cancelSamplingExecution. + Action McpSamplingExecutionAction `json:"action"` + // Error description, present when action='failure'. + Error *string `json:"error,omitempty"` + // MCP CreateMessageResult payload (with optional 'tools' extension), present when + // action='success'. Treated as opaque at the schema layer; consumers should + // construct/consume it per the MCP CreateMessageResult shape. + Result *McpExecuteSamplingResult `json:"result,omitempty"` +} + // Schema for the `McpServer` type. // Experimental: McpServer is part of an experimental API and may change or be removed. type McpServer struct { @@ -818,6 +1401,152 @@ type McpServerList struct { Servers []McpServer `json:"servers"` } +// Mode controlling how MCP server env values are resolved (`direct` or `indirect`). +// Experimental: McpSetEnvValueModeParams is part of an experimental API and may change or +// be removed. +type McpSetEnvValueModeParams struct { + // How environment-variable values supplied to MCP servers are resolved. "direct" passes + // literal string values; "indirect" treats values as references (e.g. names of environment + // variables on the host) that the runtime resolves before launch. Defaults to the runtime's + // startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI + // prompt mode and ACP) set this to "direct". + Mode McpSetEnvValueModeDetails `json:"mode"` +} + +// Env-value mode recorded on the session after the update. +// Experimental: McpSetEnvValueModeResult is part of an experimental API and may change or +// be removed. +type McpSetEnvValueModeResult struct { + // Mode recorded on the session after the update + Mode McpSetEnvValueModeDetails `json:"mode"` +} + +// Model identifier and token limits used to compute the context-info breakdown. +// Experimental: MetadataContextInfoRequest is part of an experimental API and may change or +// be removed. +type MetadataContextInfoRequest struct { + // Maximum output tokens allowed by the target model. Pass 0 if unknown. + OutputTokenLimit int64 `json:"outputTokenLimit"` + // Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. + PromptTokenLimit int64 `json:"promptTokenLimit"` + // Model identifier used for tokenization. Omit to use the session default. Used both for + // token counting and to compute display values. + SelectedModel *string `json:"selectedModel,omitempty"` +} + +// Token breakdown for the session's current context window, or null if uninitialized. +// Experimental: MetadataContextInfoResult is part of an experimental API and may change or +// be removed. +type MetadataContextInfoResult struct { + // Token breakdown for the current context window, or null if the session has not yet been + // initialized (no system prompt or tool metadata cached). + ContextInfo *SessionContextInfo `json:"contextInfo,omitempty"` +} + +// Indicates whether the local session is currently processing a turn or background +// continuation. +// Experimental: MetadataIsProcessingResult is part of an experimental API and may change or +// be removed. +type MetadataIsProcessingResult struct { + // Whether the session is currently processing user/agent messages. False for non-local + // sessions (which don't run a local agentic loop). Reflects an in-flight turn or background + // continuation. + Processing bool `json:"processing"` +} + +// Model identifier to use when re-tokenizing the session's existing messages. +// Experimental: MetadataRecomputeContextTokensRequest is part of an experimental API and +// may change or be removed. +type MetadataRecomputeContextTokensRequest struct { + // Model identifier used for tokenization. The runtime token-counts both chat-context and + // system-context messages against this model. + ModelID string `json:"modelId"` +} + +// Re-tokenize the session's existing messages against `modelId` and return the token +// totals. Useful for hosts that want an initial estimate of context usage on session +// resume, before the next agent turn fires `session.context_info_changed` events. Returns +// zeros for an empty session. +// Experimental: MetadataRecomputeContextTokensResult is part of an experimental API and may +// change or be removed. +type MetadataRecomputeContextTokensResult struct { + // Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). + MessagesTokenCount int64 `json:"messagesTokenCount"` + // Tokens contributed by system/developer prompt snapshots. + SystemTokenCount int64 `json:"systemTokenCount"` + // Sum of tokens across chat-context and system-context messages currently held by the + // session. + TotalTokens int64 `json:"totalTokens"` +} + +// Updated working-directory/git context to record on the session. +// Experimental: MetadataRecordContextChangeRequest is part of an experimental API and may +// change or be removed. +type MetadataRecordContextChangeRequest struct { + // Updated working directory and git context. Emitted as the new payload of + // `session.context_changed`. + Context SessionWorkingDirectoryContext `json:"context"` +} + +// Notify the session that its working directory context has changed. Emits a +// `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline +// UI) can react. Use this when the host has detected a cwd/branch/repo change outside the +// session's normal lifecycle (e.g., after a shell command in interactive mode). +// Experimental: MetadataRecordContextChangeResult is part of an experimental API and may +// change or be removed. +type MetadataRecordContextChangeResult struct { +} + +// Absolute path to set as the session's new working directory. +// Experimental: MetadataSetWorkingDirectoryRequest is part of an experimental API and may +// change or be removed. +type MetadataSetWorkingDirectoryRequest struct { + // Absolute path to set as the session's working directory. The runtime updates the + // session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) + // anchor to it. + WorkingDirectory string `json:"workingDirectory"` +} + +// Update the session's working directory. Used by the host when the user explicitly changes +// cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any +// related side-effects (file index, etc.); this method only updates the session's own +// recorded path. +// Experimental: MetadataSetWorkingDirectoryResult is part of an experimental API and may +// change or be removed. +type MetadataSetWorkingDirectoryResult struct { + // Working directory after the update + WorkingDirectory string `json:"workingDirectory"` +} + +// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are +// immutable for the lifetime of the session. +// Experimental: MetadataSnapshotRemoteMetadata is part of an experimental API and may +// change or be removed. +type MetadataSnapshotRemoteMetadata struct { + // The pull request number the remote session is associated with, if any. + PullRequestNumber *int64 `json:"pullRequestNumber,omitempty"` + // The repository the remote session targets. + Repository MetadataSnapshotRemoteMetadataRepository `json:"repository"` + // The original resource identifier (task ID or PR node ID), preserved across event-replay + // reconstructions. Falls back to `sessionId` when absent. + ResourceID *string `json:"resourceId,omitempty"` + // Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` + // invocation. + TaskType *MetadataSnapshotRemoteMetadataTaskType `json:"taskType,omitempty"` +} + +// The repository the remote session targets. +// Experimental: MetadataSnapshotRemoteMetadataRepository is part of an experimental API and +// may change or be removed. +type MetadataSnapshotRemoteMetadataRepository struct { + // The branch the remote session is operating on. + Branch string `json:"branch"` + // The GitHub repository name (without owner). + Name string `json:"name"` + // The GitHub owner (user or organization) of the target repository. + Owner string `json:"owner"` +} + // Schema for the `Model` type. type Model struct { // Billing information @@ -954,6 +1683,21 @@ type ModelPolicy struct { Terms *string `json:"terms,omitempty"` } +// Reasoning effort level to apply to the currently selected model. +type ModelSetReasoningEffortRequest struct { + // Reasoning effort level to apply to the currently selected model. The host is responsible + // for validating the value against the model's supported levels before calling. + ReasoningEffort string `json:"reasoningEffort"` +} + +// Update the session's reasoning effort without changing the selected model. Use `switchTo` +// instead when you also need to change the model. The runtime stores the effort on the +// session and applies it to subsequent turns. +type ModelSetReasoningEffortResult struct { + // Reasoning effort level recorded on the session after the update + ReasoningEffort string `json:"reasoningEffort"` +} + type ModelsListRequest struct { // GitHub token for per-user model listing. When provided, resolves this token to determine // the user's Copilot plan and available models instead of using the global auth. @@ -990,13 +1734,46 @@ type NameGetResult struct { Name *string `json:"name"` } +// Auto-generated session summary to apply as the session's name when no user-set name +// exists. +type NameSetAutoRequest struct { + // Auto-generated session summary. Empty/whitespace-only values are ignored; values are + // trimmed before persisting. + Summary string `json:"summary"` +} + +// Indicates whether the auto-generated summary was applied as the session's name. +type NameSetAutoResult struct { + // Whether the auto-generated summary was persisted. False if the session already has a + // user-set name, the summary normalized to empty, or the session does not have a workspace. + Applied bool `json:"applied"` +} + // New friendly name to apply to the session. type NameSetRequest struct { // New session name (1–100 characters, trimmed of leading/trailing whitespace) Name string `json:"name"` } -// Decision to apply to a pending permission request. +// Schema for the `PendingPermissionRequest` type. +type PendingPermissionRequest struct { + // The user-facing permission prompt details (commands, write, read, mcp, url, memory, + // custom-tool, path, hook) + Request PermissionPromptRequest `json:"request"` + // Unique identifier for the pending permission request + RequestID string `json:"requestId"` +} + +// List of pending permission requests reconstructed from event history. +type PendingPermissionRequestList struct { + // Pending permission prompts reconstructed from the session's event history. Equivalent to + // the set of `permission.requested` events that have not yet been followed by a matching + // `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts + // that were emitted before the client attached to the session. + Items []PendingPermissionRequest `json:"items"` +} + +// The client's response to the pending permission prompt type PermissionDecision interface { permissionDecision() Kind() PermissionDecisionKind @@ -1012,11 +1789,44 @@ func (r RawPermissionDecisionData) Kind() PermissionDecisionKind { return r.Discriminator } +// Schema for the `PermissionDecisionApproved` type. +type PermissionDecisionApproved struct { +} + +func (PermissionDecisionApproved) permissionDecision() {} +func (PermissionDecisionApproved) Kind() PermissionDecisionKind { + return PermissionDecisionKindApproved +} + +// Schema for the `PermissionDecisionApprovedForLocation` type. +type PermissionDecisionApprovedForLocation struct { + // The approval to persist for this location + Approval UserToolSessionApproval `json:"approval"` + // The location key (git root or cwd) to persist the approval to + LocationKey string `json:"locationKey"` +} + +func (PermissionDecisionApprovedForLocation) permissionDecision() {} +func (PermissionDecisionApprovedForLocation) Kind() PermissionDecisionKind { + return PermissionDecisionKindApprovedForLocation +} + +// Schema for the `PermissionDecisionApprovedForSession` type. +type PermissionDecisionApprovedForSession struct { + // The approval to add as a session-scoped rule + Approval UserToolSessionApproval `json:"approval"` +} + +func (PermissionDecisionApprovedForSession) permissionDecision() {} +func (PermissionDecisionApprovedForSession) Kind() PermissionDecisionKind { + return PermissionDecisionKindApprovedForSession +} + // Schema for the `PermissionDecisionApproveForLocation` type. type PermissionDecisionApproveForLocation struct { - // The approval to persist for this location + // Approval to persist for this location Approval PermissionDecisionApproveForLocationApproval `json:"approval"` - // The location key (git root or cwd) to persist the approval to + // Location key (git root or cwd) to persist the approval to LocationKey string `json:"locationKey"` } @@ -1027,9 +1837,9 @@ func (PermissionDecisionApproveForLocation) Kind() PermissionDecisionKind { // Schema for the `PermissionDecisionApproveForSession` type. type PermissionDecisionApproveForSession struct { - // The approval to add as a session-scoped rule + // Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) Approval PermissionDecisionApproveForSessionApproval `json:"approval,omitempty"` - // The URL domain to approve for this session + // URL domain to approve for the rest of the session (URL prompts only) Domain *string `json:"domain,omitempty"` } @@ -1049,7 +1859,7 @@ func (PermissionDecisionApproveOnce) Kind() PermissionDecisionKind { // Schema for the `PermissionDecisionApprovePermanently` type. type PermissionDecisionApprovePermanently struct { - // The URL domain to approve permanently + // URL domain to approve permanently Domain string `json:"domain"` } @@ -1058,9 +1868,79 @@ func (PermissionDecisionApprovePermanently) Kind() PermissionDecisionKind { return PermissionDecisionKindApprovePermanently } +// Schema for the `PermissionDecisionCancelled` type. +type PermissionDecisionCancelled struct { + // Optional explanation of why the request was cancelled + Reason *string `json:"reason,omitempty"` +} + +func (PermissionDecisionCancelled) permissionDecision() {} +func (PermissionDecisionCancelled) Kind() PermissionDecisionKind { + return PermissionDecisionKindCancelled +} + +// Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. +type PermissionDecisionDeniedByContentExclusionPolicy struct { + // Human-readable explanation of why the path was excluded + Message string `json:"message"` + // File path that triggered the exclusion + Path string `json:"path"` +} + +func (PermissionDecisionDeniedByContentExclusionPolicy) permissionDecision() {} +func (PermissionDecisionDeniedByContentExclusionPolicy) Kind() PermissionDecisionKind { + return PermissionDecisionKindDeniedByContentExclusionPolicy +} + +// Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. +type PermissionDecisionDeniedByPermissionRequestHook struct { + // Whether to interrupt the current agent turn + Interrupt *bool `json:"interrupt,omitempty"` + // Optional message from the hook explaining the denial + Message *string `json:"message,omitempty"` +} + +func (PermissionDecisionDeniedByPermissionRequestHook) permissionDecision() {} +func (PermissionDecisionDeniedByPermissionRequestHook) Kind() PermissionDecisionKind { + return PermissionDecisionKindDeniedByPermissionRequestHook +} + +// Schema for the `PermissionDecisionDeniedByRules` type. +type PermissionDecisionDeniedByRules struct { + // Rules that denied the request + Rules []PermissionRule `json:"rules"` +} + +func (PermissionDecisionDeniedByRules) permissionDecision() {} +func (PermissionDecisionDeniedByRules) Kind() PermissionDecisionKind { + return PermissionDecisionKindDeniedByRules +} + +// Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. +type PermissionDecisionDeniedInteractivelyByUser struct { + // Optional feedback from the user explaining the denial + Feedback *string `json:"feedback,omitempty"` + // Whether to force-reject the current agent turn + ForceReject *bool `json:"forceReject,omitempty"` +} + +func (PermissionDecisionDeniedInteractivelyByUser) permissionDecision() {} +func (PermissionDecisionDeniedInteractivelyByUser) Kind() PermissionDecisionKind { + return PermissionDecisionKindDeniedInteractivelyByUser +} + +// Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. +type PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser struct { +} + +func (PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser) permissionDecision() {} +func (PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser) Kind() PermissionDecisionKind { + return PermissionDecisionKindDeniedNoApprovalRuleAndCouldNotRequestFromUser +} + // Schema for the `PermissionDecisionReject` type. type PermissionDecisionReject struct { - // Optional feedback from the user explaining the denial + // Optional feedback explaining the rejection Feedback *string `json:"feedback,omitempty"` } @@ -1078,7 +1958,7 @@ func (PermissionDecisionUserNotAvailable) Kind() PermissionDecisionKind { return PermissionDecisionKindUserNotAvailable } -// The approval to persist for this location +// Approval to persist for this location type PermissionDecisionApproveForLocationApproval interface { permissionDecisionApproveForLocationApproval() Kind() PermissionDecisionApproveForLocationApprovalKind @@ -1201,7 +2081,7 @@ func (PermissionDecisionApproveForLocationApprovalWrite) Kind() PermissionDecisi return PermissionDecisionApproveForLocationApprovalKindWrite } -// The approval to add as a session-scoped rule +// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) type PermissionDecisionApproveForSessionApproval interface { permissionDecisionApproveForSessionApproval() Kind() PermissionDecisionApproveForSessionApprovalKind @@ -1327,10 +2207,83 @@ func (PermissionDecisionApproveForSessionApprovalWrite) Kind() PermissionDecisio type PermissionDecisionRequest struct { // Request ID of the pending permission request RequestID string `json:"requestId"` - // Decision to apply to a pending permission request. + // The client's response to the pending permission prompt Result PermissionDecision `json:"result"` } +// Directory path to add to the session's allowed directories. +type PermissionPathsAddParams struct { + // Directory to add to the allow-list. The runtime resolves and validates the path before + // adding. + Path string `json:"path"` +} + +// Path to evaluate against the session's allowed directories. +type PermissionPathsAllowedCheckParams struct { + // Path to check against the session's allowed directories + Path string `json:"path"` +} + +// Indicates whether the supplied path is within the session's allowed directories. +type PermissionPathsAllowedCheckResult struct { + // Whether the path is within the session's allowed directories + Allowed bool `json:"allowed"` +} + +// If specified, replaces the session's path-permission policy. The runtime constructs the +// appropriate PathManager based on these inputs (rooted at the session's working +// directory). Omit to leave the current path policy unchanged. +type PermissionPathsConfig struct { + // Additional directories to allow tool access to (in addition to the session's working + // directory). When `unrestricted` is true, these are still pre-populated on the + // UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention + // completion). + AdditionalDirectories []string `json:"additionalDirectories,omitempty"` + // Whether to include the system temp directory in the allowed list (defaults to true). + // Ignored when `unrestricted` is true. + IncludeTempDirectory *bool `json:"includeTempDirectory,omitempty"` + // If true, the runtime allows access to all paths without prompting. Equivalent to + // constructing an UnrestrictedPathManager. + Unrestricted *bool `json:"unrestricted,omitempty"` + // Workspace root path (special-cased to be allowed even before the directory exists). + // Ignored when `unrestricted` is true. + WorkspacePath *string `json:"workspacePath,omitempty"` +} + +// Snapshot of the session's allow-listed directories and primary working directory. +type PermissionPathsList struct { + // All directories currently allowed for tool access on this session. + Directories []string `json:"directories"` + // The primary working directory for this session. + Primary string `json:"primary"` +} + +// Directory path to set as the session's new primary working directory. +type PermissionPathsUpdatePrimaryParams struct { + // Directory to set as the new primary working directory for the session's permission policy. + Path string `json:"path"` +} + +// Path to evaluate against the session's workspace (primary) directory. +type PermissionPathsWorkspaceCheckParams struct { + // Path to check against the session workspace directory + Path string `json:"path"` +} + +// Indicates whether the supplied path is within the session's workspace directory. +type PermissionPathsWorkspaceCheckResult struct { + // Whether the path is within the session workspace directory + Allowed bool `json:"allowed"` +} + +// Notification payload describing the permission prompt that the client just rendered. +type PermissionPromptShownNotification struct { + // Human-readable description of the prompt the user is being asked to approve. Used by the + // runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, + // desktop notification). + Message string `json:"message"` +} + // Indicates whether the permission decision was applied; false when the request was already // resolved. type PermissionRequestResult struct { @@ -1338,20 +2291,142 @@ type PermissionRequestResult struct { Success bool `json:"success"` } -// No parameters; clears all session-scoped tool permission approvals. -type PermissionsResetSessionApprovalsRequest struct { +// Schema for the `PermissionRule` type. +type PermissionRule struct { + // Argument value matched against the request, or null when the rule kind has no argument + // (e.g. 'read', 'write', 'memory'). + Argument *string `json:"argument"` + // The rule kind, such as Shell or GitHubMCP + Kind string `json:"kind"` } -// Indicates whether the operation succeeded. -type PermissionsResetSessionApprovalsResult struct { - // Whether the operation succeeded - Success bool `json:"success"` +// If specified, replaces the session's approved/denied permission rules. Omit to leave the +// current rules unchanged. +type PermissionRulesSet struct { + // Rules that auto-approve matching requests + Approved []PermissionRule `json:"approved"` + // Rules that auto-deny matching requests + Denied []PermissionRule `json:"denied"` } -// Whether to auto-approve all tool permission requests for the rest of the session. -type PermissionsSetApproveAllRequest struct { - // Whether to auto-approve all tool permission requests +// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. +type PermissionsConfigureAdditionalContentExclusionPolicy struct { + LastUpdatedAt any `json:"last_updated_at"` + Rules []PermissionsConfigureAdditionalContentExclusionPolicyRule `json:"rules"` + // Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` + // enumeration. + Scope PermissionsConfigureAdditionalContentExclusionPolicyScope `json:"scope"` +} + +// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. +type PermissionsConfigureAdditionalContentExclusionPolicyRule struct { + IfAnyMatch []string `json:"ifAnyMatch,omitempty"` + IfNoneMatch []string `json:"ifNoneMatch,omitempty"` + Paths []string `json:"paths"` + // Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. + Source PermissionsConfigureAdditionalContentExclusionPolicyRuleSource `json:"source"` +} + +// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. +type PermissionsConfigureAdditionalContentExclusionPolicyRuleSource struct { + Name string `json:"name"` + Type string `json:"type"` +} + +// Patch of permission policy fields to apply (omit a field to leave it unchanged). +type PermissionsConfigureParams struct { + // If specified, replaces the host-supplied GitHub Content Exclusion policies on the session + // (combined with natively-discovered policies when evaluating tool/file access). Omit to + // leave the current policies unchanged. + AdditionalContentExclusionPolicies []PermissionsConfigureAdditionalContentExclusionPolicy `json:"additionalContentExclusionPolicies,omitempty"` + // If specified, sets whether path/URL read permission requests are auto-approved. Omit to + // leave the current value unchanged. + ApproveAllReadPermissionRequests *bool `json:"approveAllReadPermissionRequests,omitempty"` + // If specified, sets whether tool permission requests are auto-approved without prompting. + // Omit to leave the current value unchanged. + ApproveAllToolPermissionRequests *bool `json:"approveAllToolPermissionRequests,omitempty"` + // If specified, replaces the session's path-permission policy. The runtime constructs the + // appropriate PathManager based on these inputs (rooted at the session's working + // directory). Omit to leave the current path policy unchanged. + Paths *PermissionPathsConfig `json:"paths,omitempty"` + // If specified, replaces the session's approved/denied permission rules. Omit to leave the + // current rules unchanged. + Rules *PermissionRulesSet `json:"rules,omitempty"` + // If specified, replaces the session's URL-permission policy. The runtime constructs a + // fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy + // unchanged. + Urls *PermissionUrlsConfig `json:"urls,omitempty"` +} + +// Indicates whether the operation succeeded. +type PermissionsConfigureResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Scope and add/remove instructions for modifying session- or location-scoped permission +// rules. +type PermissionsModifyRulesParams struct { + // Rules to add to the scope. Applied before `remove`/`removeAll`. + Add []PermissionRule `json:"add,omitempty"` + // Specific rules to remove from the scope. Ignored when `removeAll` is true. + Remove []PermissionRule `json:"remove,omitempty"` + // When true, removes every rule currently in the scope (after any `add` is applied). Useful + // for clearing the location scope wholesale. + RemoveAll *bool `json:"removeAll,omitempty"` + // Whether the change applies to ephemeral session-scoped rules (cleared at session end) or + // to location-scoped rules persisted via the location-permissions config file. + Scope PermissionsModifyRulesScope `json:"scope"` +} + +// Indicates whether the operation succeeded. +type PermissionsModifyRulesResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Indicates whether the operation succeeded. +type PermissionsNotifyPromptShownResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Indicates whether the operation succeeded. +type PermissionsPathsAddResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// No parameters; returns the session's allow-listed directories. +type PermissionsPathsListRequest struct { +} + +// Indicates whether the operation succeeded. +type PermissionsPathsUpdatePrimaryResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// No parameters; returns currently-pending permission requests for the session. +type PermissionsPendingRequestsRequest struct { +} + +// No parameters; clears all session-scoped tool permission approvals. +type PermissionsResetSessionApprovalsRequest struct { +} + +// Indicates whether the operation succeeded. +type PermissionsResetSessionApprovalsResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Allow-all toggle for tool permission requests, with an optional telemetry source. +type PermissionsSetApproveAllRequest struct { + // Whether to auto-approve all tool permission requests Enabled bool `json:"enabled"` + // Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. + Source *PermissionsSetApproveAllSource `json:"source,omitempty"` } // Indicates whether the operation succeeded. @@ -1360,21 +2435,60 @@ type PermissionsSetApproveAllResult struct { Success bool `json:"success"` } +// Toggles whether permission prompts should be bridged into session events for this client. +type PermissionsSetRequiredRequest struct { + // Whether the client wants `permission.requested` events bridged from the session-owned + // permission service. CLI clients that render prompt UI set this to `true` for as long as + // their listener is mounted; headless callers leave it unset (the default is `false`). + Required bool `json:"required"` +} + +// Indicates whether the operation succeeded. +type PermissionsSetRequiredResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Indicates whether the operation succeeded. +type PermissionsUrlsSetUnrestrictedModeResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// If specified, replaces the session's URL-permission policy. The runtime constructs a +// fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy +// unchanged. +type PermissionUrlsConfig struct { + // Initial list of allowed URL/domain patterns. Patterns may include path components. + // Ignored when `unrestricted` is true. + InitialAllowed []string `json:"initialAllowed,omitempty"` + // If true, the runtime allows access to all URLs without prompting. Initial allow-list is + // ignored when this is true. + Unrestricted *bool `json:"unrestricted,omitempty"` +} + +// Whether the URL-permission policy should run in unrestricted mode. +type PermissionUrlsSetUnrestrictedModeParams struct { + // Whether to allow access to all URLs without prompting. Toggles the runtime's + // URL-permission policy in place. + Enabled bool `json:"enabled"` +} + // Optional message to echo back to the caller. type PingRequest struct { // Optional message to echo back Message *string `json:"message,omitempty"` } -// Server liveness response, including the echoed message, current timestamp, and protocol -// version. +// Server liveness response, including the echoed message, current server timestamp, and +// protocol version. type PingResult struct { // Echoed message (or default greeting) Message string `json:"message"` // Server protocol version number ProtocolVersion int64 `json:"protocolVersion"` - // Server timestamp in milliseconds - Timestamp int64 `json:"timestamp"` + // ISO 8601 timestamp when the server handled the ping + Timestamp time.Time `json:"timestamp"` } // Existence, contents, and resolved path of the session plan file. @@ -1413,7 +2527,7 @@ type PluginList struct { Plugins []Plugin `json:"plugins"` } -// Result of the queued command execution +// Result of the queued command execution. type QueuedCommandResult interface { queuedCommandResult() Handled() bool @@ -1421,7 +2535,8 @@ type QueuedCommandResult interface { // Schema for the `QueuedCommandHandled` type. type QueuedCommandHandled struct { - // If true, stop processing remaining queued items + // When true, the runtime will not process subsequent queued commands until a new request + // comes in. StopProcessingQueue *bool `json:"stopProcessingQueue,omitempty"` } @@ -1439,6 +2554,78 @@ func (QueuedCommandNotHandled) Handled() bool { return false } +// Schema for the `QueuePendingItems` type. +// Experimental: QueuePendingItems is part of an experimental API and may change or be +// removed. +type QueuePendingItems struct { + // Human-readable text to display for this queue entry in the UI + DisplayText string `json:"displayText"` + // Whether this item is a queued user message or a queued slash command / model change + Kind QueuePendingItemsKind `json:"kind"` +} + +// Snapshot of the session's pending queued items and immediate-steering messages. +// Experimental: QueuePendingItemsResult is part of an experimental API and may change or be +// removed. +type QueuePendingItemsResult struct { + // Pending queued items in submission order. Includes user messages, queued slash commands, + // and queued model changes; omits internal system items. + Items []QueuePendingItems `json:"items"` + // Display text for messages currently in the immediate steering queue (interjections sent + // during a running turn). + SteeringMessages []string `json:"steeringMessages"` +} + +// Indicates whether a user-facing pending item was removed. +// Experimental: QueueRemoveMostRecentResult is part of an experimental API and may change +// or be removed. +type QueueRemoveMostRecentResult struct { + // True if a user-facing pending item was removed (LIFO across both queues); false when no + // removable items remained. + Removed bool `json:"removed"` +} + +// Event type to register consumer interest for, used by runtime gating logic. +// Experimental: RegisterEventInterestParams is part of an experimental API and may change +// or be removed. +type RegisterEventInterestParams struct { + // The event type the consumer wants the runtime to treat as 'observed' for + // behavior-switching gating. Some runtime code paths inspect whether any consumer is + // interested in a specific event type and choose a different implementation accordingly + // (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full + // interactive OAuth flow to the consumer; when no interest is registered the runtime + // installs a browserless fallback that silently reuses cached tokens). SDK clients that + // long-poll events do NOT automatically appear as listeners to these gating checks — they + // must explicitly call `registerInterest` for each event type they want the runtime to + // count as having a consumer. Multiple registrations for the same event type from the same + // or different consumers are tracked independently and must each be released. See: + // `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, + // `user_input.requested`, `elicitation.requested`, `command.queued`, + // `exit_plan_mode.requested`. + EventType string `json:"eventType"` +} + +// Opaque handle representing an event-type interest registration. +// Experimental: RegisterEventInterestResult is part of an experimental API and may change +// or be removed. +type RegisterEventInterestResult struct { + // Opaque handle for this registration. Pass to releaseInterest to release. Each call to + // registerInterest produces a fresh handle, even when the same eventType is registered + // multiple times. + Handle string `json:"handle"` +} + +// Opaque handle previously returned by `registerInterest` to release. +// Experimental: ReleaseEventInterestParams is part of an experimental API and may change or +// be removed. +type ReleaseEventInterestParams struct { + // Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown + // or already-released handle is a no-op (returns success). When the last outstanding handle + // for an event type is released, the runtime reverts to its 'no consumer' code path for + // that event type. + Handle string `json:"handle"` +} + // Optional remote session mode ("off", "export", or "on"); defaults to enabling both export // and remote steering. // Experimental: RemoteEnableRequest is part of an experimental API and may change or be @@ -1459,6 +2646,24 @@ type RemoteEnableResult struct { URL *string `json:"url,omitempty"` } +// New remote-steerability state to persist as a `session.remote_steerable_changed` event. +// Experimental: RemoteNotifySteerableChangedRequest is part of an experimental API and may +// change or be removed. +type RemoteNotifySteerableChangedRequest struct { + // Whether the session now supports remote steering via GitHub. The runtime persists this as + // a `session.remote_steerable_changed` event so resume/replay sees the up-to-date + // capability. + RemoteSteerable bool `json:"remoteSteerable"` +} + +// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the +// host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a +// remote exporter that the runtime does not directly own. +// Experimental: RemoteNotifySteerableChangedResult is part of an experimental API and may +// change or be removed. +type RemoteNotifySteerableChangedResult struct { +} + // Remote session connection result. // Experimental: RemoteSessionConnectionResult is part of an experimental API and may change // or be removed. @@ -1469,6 +2674,221 @@ type RemoteSessionConnectionResult struct { SessionID string `json:"sessionId"` } +// Schema for the `ScheduleEntry` type. +// Experimental: ScheduleEntry is part of an experimental API and may change or be removed. +type ScheduleEntry struct { + // Display-only label for the prompt as shown in the UI (e.g. `/skill-name` for a + // skill-invocation schedule). The actual enqueued prompt is `prompt`. + DisplayPrompt *string `json:"displayPrompt,omitempty"` + // Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt + // from the event log). + ID int64 `json:"id"` + // Interval between scheduled ticks, in milliseconds. + IntervalMs int64 `json:"intervalMs"` + // ISO 8601 timestamp when the next tick is scheduled to fire. + NextRunAt time.Time `json:"nextRunAt"` + // Prompt text that gets enqueued on every tick. + Prompt string `json:"prompt"` + // Whether the schedule re-arms after each tick (`/every`) or fires once (`/after`). + Recurring bool `json:"recurring"` +} + +// Snapshot of the currently active recurring prompts for this session. +// Experimental: ScheduleList is part of an experimental API and may change or be removed. +type ScheduleList struct { + // Active scheduled prompts, ordered by id. + Entries []ScheduleEntry `json:"entries"` +} + +// Identifier of the scheduled prompt to remove. +// Experimental: ScheduleStopRequest is part of an experimental API and may change or be +// removed. +type ScheduleStopRequest struct { + // Id of the scheduled prompt to remove. + ID int64 `json:"id"` +} + +// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. +// Experimental: ScheduleStopResult is part of an experimental API and may change or be +// removed. +type ScheduleStopResult struct { + // The removed entry, or omitted if no entry matched. + Entry *ScheduleEntry `json:"entry,omitempty"` +} + +// A user message attachment — a file, directory, code selection, blob, or GitHub reference +type SendAttachment interface { + sendAttachment() + Type() SendAttachmentType +} + +type RawSendAttachmentData struct { + Discriminator SendAttachmentType + Raw json.RawMessage +} + +func (RawSendAttachmentData) sendAttachment() {} +func (r RawSendAttachmentData) Type() SendAttachmentType { + return r.Discriminator +} + +// Blob attachment with inline base64-encoded data +type SendAttachmentBlob struct { + // Base64-encoded content + Data string `json:"data"` + // User-facing display name for the attachment + DisplayName *string `json:"displayName,omitempty"` + // MIME type of the inline data + MIMEType string `json:"mimeType"` +} + +func (SendAttachmentBlob) sendAttachment() {} +func (SendAttachmentBlob) Type() SendAttachmentType { + return SendAttachmentTypeBlob +} + +// Directory attachment +type SendAttachmentDirectory struct { + // User-facing display name for the attachment + DisplayName string `json:"displayName"` + // Absolute directory path + Path string `json:"path"` +} + +func (SendAttachmentDirectory) sendAttachment() {} +func (SendAttachmentDirectory) Type() SendAttachmentType { + return SendAttachmentTypeDirectory +} + +// File attachment +type SendAttachmentFile struct { + // User-facing display name for the attachment + DisplayName string `json:"displayName"` + // Optional line range to scope the attachment to a specific section of the file + LineRange *SendAttachmentFileLineRange `json:"lineRange,omitempty"` + // Absolute file path + Path string `json:"path"` +} + +func (SendAttachmentFile) sendAttachment() {} +func (SendAttachmentFile) Type() SendAttachmentType { + return SendAttachmentTypeFile +} + +// GitHub issue, pull request, or discussion reference +type SendAttachmentGithubReference struct { + // Issue, pull request, or discussion number + Number int64 `json:"number"` + // Type of GitHub reference + ReferenceType SendAttachmentGithubReferenceType `json:"referenceType"` + // Current state of the referenced item (e.g., open, closed, merged) + State string `json:"state"` + // Title of the referenced item + Title string `json:"title"` + // URL to the referenced item on GitHub + URL string `json:"url"` +} + +func (SendAttachmentGithubReference) sendAttachment() {} +func (SendAttachmentGithubReference) Type() SendAttachmentType { + return SendAttachmentTypeGithubReference +} + +// Code selection attachment from an editor +type SendAttachmentSelection struct { + // User-facing display name for the selection + DisplayName string `json:"displayName"` + // Absolute path to the file containing the selection + FilePath string `json:"filePath"` + // Position range of the selection within the file + Selection SendAttachmentSelectionDetails `json:"selection"` + // The selected text content + Text string `json:"text"` +} + +func (SendAttachmentSelection) sendAttachment() {} +func (SendAttachmentSelection) Type() SendAttachmentType { + return SendAttachmentTypeSelection +} + +// Optional line range to scope the attachment to a specific section of the file +type SendAttachmentFileLineRange struct { + // End line number (1-based, inclusive) + End int64 `json:"end"` + // Start line number (1-based) + Start int64 `json:"start"` +} + +// Position range of the selection within the file +type SendAttachmentSelectionDetails struct { + // End position of the selection + End SendAttachmentSelectionDetailsEnd `json:"end"` + // Start position of the selection + Start SendAttachmentSelectionDetailsStart `json:"start"` +} + +// End position of the selection +type SendAttachmentSelectionDetailsEnd struct { + // End character offset within the line (0-based) + Character int64 `json:"character"` + // End line number (0-based) + Line int64 `json:"line"` +} + +// Start position of the selection +type SendAttachmentSelectionDetailsStart struct { + // Start character offset within the line (0-based) + Character int64 `json:"character"` + // Start line number (0-based) + Line int64 `json:"line"` +} + +// Parameters for sending a user message to the session +type SendRequest struct { + // The UI mode the agent was in when this message was sent. Defaults to the session's + // current mode. + AgentMode *SendAgentMode `json:"agentMode,omitempty"` + // Optional attachments (files, directories, selections, blobs, GitHub references) to + // include with the message + Attachments []SendAttachment `json:"attachments,omitempty"` + // If false, this message will not trigger a Premium Request Unit charge. User messages + // default to billable. + Billable *bool `json:"billable,omitempty"` + // If provided, this is shown in the timeline instead of `prompt` + DisplayPrompt *string `json:"displayPrompt,omitempty"` + // How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` + // interjects during an in-progress turn. + Mode *SendMode `json:"mode,omitempty"` + // If true, adds the message to the front of the queue instead of the end + Prepend *bool `json:"prepend,omitempty"` + // The user message text + Prompt string `json:"prompt"` + // Custom HTTP headers to include in outbound model requests for this turn. Merged with + // session-level provider headers; per-turn headers augment and overwrite session-level + // headers with the same key. + RequestHeaders map[string]string `json:"requestHeaders,omitempty"` + // If set, the request will fail if the named tool is not available when this message is + // among the user messages at the start of the current exchange + RequiredTool *string `json:"requiredTool,omitempty"` + // Optional provenance tag copied to the resulting user.message event. Supported values are + // `system`, `command-*`, and `schedule-*`. + Source any `json:"source,omitempty"` + // W3C Trace Context traceparent header for distributed tracing of this agent turn + Traceparent *string `json:"traceparent,omitempty"` + // W3C Trace Context tracestate header for distributed tracing + Tracestate *string `json:"tracestate,omitempty"` + // If true, await completion of the agentic loop for this message before returning. Defaults + // to false (fire-and-forget). When true, the result still contains the same `messageId`; + // the caller can rely on the agent having processed the message before the call resolves. + Wait *bool `json:"wait,omitempty"` +} + +// Result of sending a user message +type SendResult struct { + // Unique identifier assigned to the message + MessageID string `json:"messageId"` +} + // Schema for the `ServerSkill` type. type ServerSkill struct { // Description of what the skill does @@ -1514,6 +2934,65 @@ type SessionAuthStatus struct { StatusMessage *string `json:"statusMessage,omitempty"` } +// Map of sessionId -> bytes freed by removing the session's workspace directory. +// Experimental: SessionBulkDeleteResult is part of an experimental API and may change or be +// removed. +type SessionBulkDeleteResult struct { + // Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions + // whose deletion failed are omitted from this map (failures are logged on the server but + // not surfaced per-id; check the map for absent IDs to detect them). + FreedBytes map[string]int64 `json:"freedBytes"` +} + +// Schema for the `SessionContext` type. +// Experimental: SessionContext is part of an experimental API and may change or be removed. +type SessionContext struct { + // Active git branch + Branch *string `json:"branch,omitempty"` + // Most recent working directory for this session + Cwd string `json:"cwd"` + // Git repository root, if the cwd was inside a git repo + GitRoot *string `json:"gitRoot,omitempty"` + // Repository host type + HostType *SessionContextHostType `json:"hostType,omitempty"` + // Repository slug in `owner/name` form, when known + Repository *string `json:"repository,omitempty"` +} + +// Token-usage breakdown for the session's current context window +// Experimental: SessionContextInfo is part of an experimental API and may change or be +// removed. +type SessionContextInfo struct { + // Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%) + BufferTokens int64 `json:"bufferTokens"` + // Token count at which background compaction starts (configurable percentage of + // promptTokenLimit) + CompactionThreshold int64 `json:"compactionThreshold"` + // Tokens consumed by user/assistant/tool messages + ConversationTokens int64 `json:"conversationTokens"` + // Total context limit for /context display. promptTokenLimit + min(32k or 64k, + // outputTokenLimit) depending on model. + Limit int64 `json:"limit"` + // The model used for token counting + ModelName string `json:"modelName"` + // Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified) + PromptTokenLimit int64 `json:"promptTokenLimit"` + // Tokens consumed by the system prompt + SystemTokens int64 `json:"systemTokens"` + // Tokens consumed by tool definitions sent to the model (excludes deferred tools) + ToolDefinitionsTokens int64 `json:"toolDefinitionsTokens"` + // Sum of system, conversation and tool-definition tokens + TotalTokens int64 `json:"totalTokens"` +} + +// The same metadata records, with summary and context fields backfilled where available. +// Experimental: SessionEnrichMetadataResult is part of an experimental API and may change +// or be removed. +type SessionEnrichMetadataResult struct { + // Same records, with summary and context backfilled + Sessions []SessionMetadata `json:"sessions"` +} + // Experimental: SessionExtensionsDisableResult is part of an experimental API and may // change or be removed. type SessionExtensionsDisableResult struct { @@ -1717,8 +3196,8 @@ type SessionFsSqliteQueryResult struct { Columns []string `json:"columns"` // Describes a filesystem error. Error *SessionFsError `json:"error,omitempty"` - // Last inserted row ID (for INSERT) - LastInsertRowid *float64 `json:"lastInsertRowid,omitempty"` + // SQLite last_insert_rowid() value for INSERT. + LastInsertRowid *int64 `json:"lastInsertRowid,omitempty"` // For SELECT: array of row objects. For others: empty array. Rows []map[string]any `json:"rows"` // Number of rows affected (for INSERT/UPDATE/DELETE) @@ -1761,6 +3240,91 @@ type SessionFsWriteFileRequest struct { SessionID string `json:"sessionId"` } +// Schema for the `SessionInstalledPlugin` type. +// Experimental: SessionInstalledPlugin is part of an experimental API and may change or be +// removed. +type SessionInstalledPlugin struct { + // Path where the plugin is cached locally + CachePath *string `json:"cache_path,omitempty"` + // Whether the plugin is currently enabled + Enabled bool `json:"enabled"` + // Installation timestamp (ISO-8601) + InstalledAt string `json:"installed_at"` + // Marketplace the plugin came from (empty string for direct repo installs) + Marketplace string `json:"marketplace"` + // Plugin name + Name string `json:"name"` + // Source descriptor for direct repo installs (when marketplace is empty) + Source *SessionInstalledPluginSource `json:"source,omitempty"` + // Installed version, if known + Version *string `json:"version,omitempty"` +} + +// Source descriptor for direct repo installs (when marketplace is empty) +// Experimental: SessionInstalledPluginSource is part of an experimental API and may change +// or be removed. +type SessionInstalledPluginSource struct { + SessionInstalledPluginSourceGithub *SessionInstalledPluginSourceGithub + SessionInstalledPluginSourceLocal *SessionInstalledPluginSourceLocal + SessionInstalledPluginSourceURL *SessionInstalledPluginSourceURL + String *string +} + +// Schema for the `SessionInstalledPluginSourceGithub` type. +// Experimental: SessionInstalledPluginSourceGithub is part of an experimental API and may +// change or be removed. +type SessionInstalledPluginSourceGithub struct { + Path *string `json:"path,omitempty"` + Ref *string `json:"ref,omitempty"` + Repo string `json:"repo"` + // Constant value. Always "github". + Source SessionInstalledPluginSourceGithubSource `json:"source"` +} + +// Schema for the `SessionInstalledPluginSourceLocal` type. +// Experimental: SessionInstalledPluginSourceLocal is part of an experimental API and may +// change or be removed. +type SessionInstalledPluginSourceLocal struct { + Path string `json:"path"` + // Constant value. Always "local". + Source SessionInstalledPluginSourceLocalSource `json:"source"` +} + +// Schema for the `SessionInstalledPluginSourceUrl` type. +// Experimental: SessionInstalledPluginSourceURL is part of an experimental API and may +// change or be removed. +type SessionInstalledPluginSourceURL struct { + Path *string `json:"path,omitempty"` + Ref *string `json:"ref,omitempty"` + // Constant value. Always "url". + Source SessionInstalledPluginSourceURLSource `json:"source"` + URL string `json:"url"` +} + +// Persisted sessions matching the filter, ordered most-recently-modified first. +// Experimental: SessionList is part of an experimental API and may change or be removed. +type SessionList struct { + // Sessions ordered most-recently-modified first + Sessions []SessionMetadata `json:"sessions"` +} + +// Queued repo-level startup prompts and the total hook command count after loading. +// Experimental: SessionLoadDeferredRepoHooksResult is part of an experimental API and may +// change or be removed. +type SessionLoadDeferredRepoHooksResult struct { + // Total hook command count (user + plugin + repo) loaded for the session by this call. + // Captured atomically with startupPrompts so callers don't need to read a separate counter. + HookCount int64 `json:"hookCount"` + // Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo + // configs were pending, or when disableAllHooks is set. + StartupPrompts []string `json:"startupPrompts"` +} + +// Experimental: SessionLspInitializeResult is part of an experimental API and may change or +// be removed. +type SessionLspInitializeResult struct { +} + // Experimental: SessionMcpDisableResult is part of an experimental API and may change or be // removed. type SessionMcpDisableResult struct { @@ -1776,6 +3340,71 @@ type SessionMcpEnableResult struct { type SessionMcpReloadResult struct { } +// Schema for the `SessionMetadata` type. +// Experimental: SessionMetadata is part of an experimental API and may change or be removed. +type SessionMetadata struct { + // Schema for the `SessionContext` type. + Context *SessionContext `json:"context,omitempty"` + // True for remote (GitHub) sessions; false for local + IsRemote bool `json:"isRemote"` + // GitHub task ID, when this local session is bound to one. Only present for local sessions + // exported to remote control. + McTaskID *string `json:"mcTaskId,omitempty"` + // Last-modified time of the session's persisted state, as ISO 8601 + ModifiedTime string `json:"modifiedTime"` + // Optional human-friendly name set via /rename + Name *string `json:"name,omitempty"` + // Stable session identifier + SessionID string `json:"sessionId"` + // Session creation time as an ISO 8601 timestamp + StartTime string `json:"startTime"` + // Short summary of the session, when one has been derived + Summary *string `json:"summary,omitempty"` +} + +// Point-in-time snapshot of slow-changing session identifier and state fields +// Experimental: SessionMetadataSnapshot is part of an experimental API and may change or be +// removed. +type SessionMetadataSnapshot struct { + // True when the session was detected to be in use by another process at construction time. + // Local consumers may surface a confirmation prompt before fully attaching. Always false + // for new sessions. + AlreadyInUse bool `json:"alreadyInUse"` + // The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') + CurrentMode MetadataSnapshotCurrentMode `json:"currentMode"` + // User-provided name supplied at session construction (via `--name`), if any. Immutable + // after construction. + InitialName *string `json:"initialName,omitempty"` + // Whether this is a remote session (i.e., one whose runtime executes elsewhere and is + // steered through this process) + IsRemote bool `json:"isRemote"` + // ISO 8601 timestamp of when the session's persisted state was last modified on disk. For + // new sessions, equals startTime. For resumed sessions, reflects the previous modification + // time at construction. + ModifiedTime time.Time `json:"modifiedTime"` + // Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are + // immutable for the lifetime of the session. + RemoteMetadata *MetadataSnapshotRemoteMetadata `json:"remoteMetadata,omitempty"` + // Currently selected model identifier, if any + SelectedModel *string `json:"selectedModel,omitempty"` + // The unique identifier of the session + SessionID string `json:"sessionId"` + // ISO 8601 timestamp of when the session started + StartTime time.Time `json:"startTime"` + // Short human-readable summary of the session, if known. Omitted when no summary has been + // generated. + Summary *string `json:"summary,omitempty"` + // Absolute path to the session's current working directory + WorkingDirectory string `json:"workingDirectory"` + // Public-facing workspace metadata for this session, or null if the session has no + // associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, + // internal flags). + Workspace *WorkspaceSummary `json:"workspace,omitempty"` + // Absolute path to the session's workspace directory on disk, or null if the session has no + // associated workspace + WorkspacePath *string `json:"workspacePath"` +} + type SessionModeSetResult struct { } @@ -1788,11 +3417,132 @@ type SessionPlanDeleteResult struct { type SessionPlanUpdateResult struct { } +// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes +// freed, and the dry-run flag. +// Experimental: SessionPruneResult is part of an experimental API and may change or be +// removed. +type SessionPruneResult struct { + // Session IDs that would be deleted in dry-run mode (always empty otherwise) + Candidates []string `json:"candidates"` + // Session IDs that were deleted (always empty in dry-run mode) + Deleted []string `json:"deleted"` + // True when no deletions were actually performed + DryRun bool `json:"dryRun"` + // Total bytes freed (actual when not dry-run, projected when dry-run) + FreedBytes int64 `json:"freedBytes"` + // Session IDs that were skipped (e.g., named sessions) + Skipped []string `json:"skipped"` +} + +// Experimental: SessionQueueClearResult is part of an experimental API and may change or be +// removed. +type SessionQueueClearResult struct { +} + // Experimental: SessionRemoteDisableResult is part of an experimental API and may change or // be removed. type SessionRemoteDisableResult struct { } +// Session IDs to close, deactivate, and delete from disk. +// Experimental: SessionsBulkDeleteRequest is part of an experimental API and may change or +// be removed. +type SessionsBulkDeleteRequest struct { + // Session IDs to close, deactivate, and delete from disk + SessionIds []string `json:"sessionIds"` +} + +// Session IDs to test for live in-use locks. +// Experimental: SessionsCheckInUseRequest is part of an experimental API and may change or +// be removed. +type SessionsCheckInUseRequest struct { + // Session IDs to test for live in-use locks + SessionIds []string `json:"sessionIds"` +} + +// Session IDs from the input set that are currently in use by another process. +// Experimental: SessionsCheckInUseResult is part of an experimental API and may change or +// be removed. +type SessionsCheckInUseResult struct { + // Session IDs from the input set that are currently held by another running process via an + // alive lock file + InUse []string `json:"inUse"` +} + +// Session ID to close. +// Experimental: SessionsCloseRequest is part of an experimental API and may change or be +// removed. +type SessionsCloseRequest struct { + // Session ID to close + SessionID string `json:"sessionId"` +} + +// Closes a session: emits shutdown, flushes pending events to disk, releases the in-use +// lock, disposes the active session. Idempotent: succeeds even if the session is not +// currently active. +// Experimental: SessionsCloseResult is part of an experimental API and may change or be +// removed. +type SessionsCloseResult struct { +} + +// Session metadata records to enrich with summary and context information. +// Experimental: SessionsEnrichMetadataRequest is part of an experimental API and may change +// or be removed. +type SessionsEnrichMetadataRequest struct { + // Session metadata records to enrich. Records that already have summary and context are + // returned unchanged. + Sessions []SessionMetadata `json:"sessions"` +} + +// New auth credentials to install on the session. Omit to leave credentials unchanged. +type SessionSetCredentialsParams struct { + // The new auth credentials to install on the session. When omitted or `undefined`, the call + // is a no-op and the session's existing credentials are preserved. The runtime stores the + // value verbatim and uses it for outbound model/API requests; it does NOT re-validate or + // re-fetch the associated Copilot user response. Several variants carry secret material; + // treat this method's params as containing secrets at rest and in transit. + Credentials AuthInfo `json:"credentials,omitempty"` +} + +// Indicates whether the credential update succeeded. +type SessionSetCredentialsResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// UUID prefix to resolve to a unique session ID. +// Experimental: SessionsFindByPrefixRequest is part of an experimental API and may change +// or be removed. +type SessionsFindByPrefixRequest struct { + // UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when + // there is no match or the prefix matches multiple sessions. + Prefix string `json:"prefix"` +} + +// Session ID matching the prefix, omitted when no unique match exists. +// Experimental: SessionsFindByPrefixResult is part of an experimental API and may change or +// be removed. +type SessionsFindByPrefixResult struct { + // Omitted when no unique session matches the prefix (no match or ambiguous) + SessionID *string `json:"sessionId,omitempty"` +} + +// GitHub task ID to look up. +// Experimental: SessionsFindByTaskIDRequest is part of an experimental API and may change +// or be removed. +type SessionsFindByTaskIDRequest struct { + // GitHub task ID to look up + TaskID string `json:"taskId"` +} + +// ID of the local session bound to the given GitHub task, or omitted when none. +// Experimental: SessionsFindByTaskIDResult is part of an experimental API and may change or +// be removed. +type SessionsFindByTaskIDResult struct { + // Omitted when no local session is bound to that GitHub task + SessionID *string `json:"sessionId,omitempty"` +} + // Source session identifier to fork from, optional event-ID boundary, and optional friendly // name for the new session. // Experimental: SessionsForkRequest is part of an experimental API and may change or be @@ -1817,6 +3567,67 @@ type SessionsForkResult struct { SessionID string `json:"sessionId"` } +// Session ID whose event-log file path to compute. +// Experimental: SessionsGetEventFilePathRequest is part of an experimental API and may +// change or be removed. +type SessionsGetEventFilePathRequest struct { + // Session ID whose event-log file path to compute + SessionID string `json:"sessionId"` +} + +// Absolute path to the session's events.jsonl file on disk. +// Experimental: SessionsGetEventFilePathResult is part of an experimental API and may +// change or be removed. +type SessionsGetEventFilePathResult struct { + // Absolute path to the session's events.jsonl file + FilePath string `json:"filePath"` +} + +// Optional working-directory context used to score session relevance. +// Experimental: SessionsGetLastForContextRequest is part of an experimental API and may +// change or be removed. +type SessionsGetLastForContextRequest struct { + // Optional working-directory context used to score session relevance. When omitted the + // most-recently-modified session wins. + Context *SessionContext `json:"context,omitempty"` +} + +// Most-relevant session ID for the supplied context, or omitted when no sessions exist. +// Experimental: SessionsGetLastForContextResult is part of an experimental API and may +// change or be removed. +type SessionsGetLastForContextResult struct { + // Most-relevant session ID for the supplied context, or omitted when no sessions exist + SessionID *string `json:"sessionId,omitempty"` +} + +// Session ID to look up the persisted remote-steerable flag for. +// Experimental: SessionsGetPersistedRemoteSteerableRequest is part of an experimental API +// and may change or be removed. +type SessionsGetPersistedRemoteSteerableRequest struct { + // Session ID to look up the persisted remote-steerable flag for + SessionID string `json:"sessionId"` +} + +// The session's persisted remote-steerable flag, or omitted when no value has been +// persisted. +// Experimental: SessionsGetPersistedRemoteSteerableResult is part of an experimental API +// and may change or be removed. +type SessionsGetPersistedRemoteSteerableResult struct { + // The session's persisted remote-steerable flag if recorded; omitted when no value has been + // persisted + RemoteSteerable *bool `json:"remoteSteerable,omitempty"` +} + +type SessionShutdownResult struct { +} + +// Map of sessionId -> on-disk size in bytes for each session's workspace directory. +// Experimental: SessionSizes is part of an experimental API and may change or be removed. +type SessionSizes struct { + // Map of sessionId -> on-disk size in bytes for the session's workspace directory + Sizes map[string]int64 `json:"sizes"` +} + // Experimental: SessionSkillsDisableResult is part of an experimental API and may change or // be removed. type SessionSkillsDisableResult struct { @@ -1827,7 +3638,249 @@ type SessionSkillsDisableResult struct { type SessionSkillsEnableResult struct { } -type SessionSuspendResult struct { +// Experimental: SessionSkillsEnsureLoadedResult is part of an experimental API and may +// change or be removed. +type SessionSkillsEnsureLoadedResult struct { +} + +// Optional metadata-load limit and context filter applied to the returned sessions. +// Experimental: SessionsListRequest is part of an experimental API and may change or be +// removed. +type SessionsListRequest struct { + // Optional filter applied to the returned sessions + Filter *SessionsListRequestFilter `json:"filter,omitempty"` + // When provided, only the first N sessions (sorted by modification time, newest first) load + // full metadata; remaining sessions return basic info only. Use 0 to return only basic info + // for every session. + MetadataLimit *int64 `json:"metadataLimit,omitempty"` +} + +// Optional filter applied to the returned sessions +type SessionsListRequestFilter struct { + // Match sessions whose context.branch equals this value + Branch *string `json:"branch,omitempty"` + // Match sessions whose context.cwd equals this value + Cwd *string `json:"cwd,omitempty"` + // Match sessions whose context.gitRoot equals this value + GitRoot *string `json:"gitRoot,omitempty"` + // Match sessions whose context.repository equals this value + Repository *string `json:"repository,omitempty"` +} + +// Active session ID whose deferred repo-level hooks should be loaded. +// Experimental: SessionsLoadDeferredRepoHooksRequest is part of an experimental API and may +// change or be removed. +type SessionsLoadDeferredRepoHooksRequest struct { + // Active session ID whose deferred repo-level hooks should be loaded + SessionID string `json:"sessionId"` +} + +// Age threshold and optional flags controlling which old sessions are pruned (or simulated +// when dryRun is true). +// Experimental: SessionsPruneOldRequest is part of an experimental API and may change or be +// removed. +type SessionsPruneOldRequest struct { + // When true, only report what would be deleted without performing any deletion + DryRun *bool `json:"dryRun,omitempty"` + // Session IDs that should never be considered for pruning + ExcludeSessionIds []string `json:"excludeSessionIds,omitempty"` + // When true, named sessions (set via /rename) are also eligible for pruning + IncludeNamed *bool `json:"includeNamed,omitempty"` + // Delete sessions whose modifiedTime is at least this many days old + OlderThanDays int64 `json:"olderThanDays"` +} + +// Session ID whose in-use lock should be released. +// Experimental: SessionsReleaseLockRequest is part of an experimental API and may change or +// be removed. +type SessionsReleaseLockRequest struct { + // Session ID whose in-use lock should be released + SessionID string `json:"sessionId"` +} + +// Release the in-use lock held by this process for the given session. No-op when this +// process does not currently hold a lock for the session. +// Experimental: SessionsReleaseLockResult is part of an experimental API and may change or +// be removed. +type SessionsReleaseLockResult struct { +} + +// Active session ID and an optional flag for deferring repo-level hooks until folder trust. +// Experimental: SessionsReloadPluginHooksRequest is part of an experimental API and may +// change or be removed. +type SessionsReloadPluginHooksRequest struct { + // When true, skip repo-level hooks. Use before folder trust is confirmed; + // loadDeferredRepoHooks loads them post-trust. + DeferRepoHooks *bool `json:"deferRepoHooks,omitempty"` + // Active session ID to reload hooks for + SessionID string `json:"sessionId"` +} + +// Reload all hooks (user, plugin, optionally repo) and apply them to the active session. +// Call after installing or removing plugins so their hooks take effect immediately. No-op +// when no active session matches the given sessionId. +// Experimental: SessionsReloadPluginHooksResult is part of an experimental API and may +// change or be removed. +type SessionsReloadPluginHooksResult struct { +} + +// Session ID whose pending events should be flushed to disk. +// Experimental: SessionsSaveRequest is part of an experimental API and may change or be +// removed. +type SessionsSaveRequest struct { + // Session ID whose pending events should be flushed to disk + SessionID string `json:"sessionId"` +} + +// Flush a session's pending events to disk. No-op when no writer exists for the session +// (e.g., already closed). +// Experimental: SessionsSaveResult is part of an experimental API and may change or be +// removed. +type SessionsSaveResult struct { +} + +// Manager-wide additional plugins to register; replaces any previously-configured set. +// Experimental: SessionsSetAdditionalPluginsRequest is part of an experimental API and may +// change or be removed. +type SessionsSetAdditionalPluginsRequest struct { + // Manager-wide additional plugins to register. Replaces any previously-configured set. Pass + // an empty array to clear. + Plugins []InstalledPlugin `json:"plugins"` +} + +// Replace the manager-wide additional plugins. New session creations and subsequent hook +// reloads see the new set; already-running sessions keep their existing hook installation +// until the next reload. +// Experimental: SessionsSetAdditionalPluginsResult is part of an experimental API and may +// change or be removed. +type SessionsSetAdditionalPluginsResult struct { +} + +type SessionSuspendResult struct { +} + +// Experimental: SessionTelemetrySetFeatureOverridesResult is part of an experimental API +// and may change or be removed. +type SessionTelemetrySetFeatureOverridesResult struct { +} + +// Patch of mutable session options to apply to the running session. +// Experimental: SessionUpdateOptionsParams is part of an experimental API and may change or +// be removed. +type SessionUpdateOptionsParams struct { + // Additional content-exclusion policies to merge into the session's policy set. Opaque + // shape; see `ContentExclusionApiResponse` in the runtime. + AdditionalContentExclusionPolicies []any `json:"additionalContentExclusionPolicies,omitempty"` + // Runtime context discriminator (e.g., `cli`, `actions`). + AgentContext *string `json:"agentContext,omitempty"` + // Whether to disable the `ask_user` tool (encourages autonomous behavior). + AskUserDisabled *bool `json:"askUserDisabled,omitempty"` + // Allowlist of tool names available to this session. + AvailableTools []string `json:"availableTools,omitempty"` + // Identifier of the client driving the session. + ClientName *string `json:"clientName,omitempty"` + // Whether to include the `Co-authored-by` trailer in commit messages. + CoauthorEnabled *bool `json:"coauthorEnabled,omitempty"` + // Whether to allow auto-mode continuation across turns. + ContinueOnAutoMode *bool `json:"continueOnAutoMode,omitempty"` + // Override URL for the Copilot API endpoint. + CopilotURL *string `json:"copilotUrl,omitempty"` + // Whether to default custom agents to local-only execution. + CustomAgentsLocalOnly *bool `json:"customAgentsLocalOnly,omitempty"` + // Instruction source IDs to exclude from the system prompt. + DisabledInstructionSources []string `json:"disabledInstructionSources,omitempty"` + // Skill IDs that should be excluded from this session. + DisabledSkills []string `json:"disabledSkills,omitempty"` + // Whether to discover custom instructions on demand after successful file views (AGENTS.md + // / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with + // `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. + EnableOnDemandInstructionDiscovery *bool `json:"enableOnDemandInstructionDiscovery,omitempty"` + // Whether to surface reasoning-summary events from the model. + EnableReasoningSummaries *bool `json:"enableReasoningSummaries,omitempty"` + // Whether shell-script safety heuristics are enabled. + EnableScriptSafety *bool `json:"enableScriptSafety,omitempty"` + // Whether to stream model responses. + EnableStreaming *bool `json:"enableStreaming,omitempty"` + // How env values are passed to MCP servers (`direct` inlines literal values; `indirect` + // resolves at launch). + EnvValueMode *OptionsUpdateEnvValueMode `json:"envValueMode,omitempty"` + // Override directory for the session-events log. When unset, the runtime's default events + // log directory is used. + EventsLogDirectory *string `json:"eventsLogDirectory,omitempty"` + // Denylist of tool names for this session. + ExcludedTools []string `json:"excludedTools,omitempty"` + // Map of feature-flag IDs to their boolean enabled state. + FeatureFlags map[string]bool `json:"featureFlags,omitempty"` + // Full set of installed plugins for the session. Replaces the existing list; the runtime + // invalidates the skills cache only when the list materially changes. + InstalledPlugins []SessionInstalledPlugin `json:"installedPlugins,omitempty"` + // Stable integration identifier used for analytics and rate-limit attribution. + IntegrationID *string `json:"integrationId,omitempty"` + // Whether experimental capabilities are enabled. + IsExperimentalMode *bool `json:"isExperimentalMode,omitempty"` + // Whether interactive shell sessions are logged. + LogInteractiveShells *bool `json:"logInteractiveShells,omitempty"` + // Identifier sent to LSP-style integrations. + LspClientName *string `json:"lspClientName,omitempty"` + // Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the + // per-session schedule registry; this flag only controls tool exposure (typically gated to + // staff users). + ManageScheduleEnabled *bool `json:"manageScheduleEnabled,omitempty"` + // The model ID to use for assistant turns. + Model *string `json:"model,omitempty"` + // Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the + // runtime. + Provider any `json:"provider,omitempty"` + // Reasoning effort for the selected model (model-defined enum). + ReasoningEffort *string `json:"reasoningEffort,omitempty"` + // Whether the session is running in an interactive UI. + RunningInInteractiveMode *bool `json:"runningInInteractiveMode,omitempty"` + // Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. + SandboxConfig any `json:"sandboxConfig,omitempty"` + // Shell init profile (`None` or `NonInteractive`). + ShellInitProfile *string `json:"shellInitProfile,omitempty"` + // Per-shell process flags (e.g., `pwsh` arguments). + ShellProcessFlags []string `json:"shellProcessFlags,omitempty"` + // Additional directories to search for skills. + SkillDirectories []string `json:"skillDirectories,omitempty"` + // Whether to skip loading custom instruction sources. + SkipCustomInstructions *bool `json:"skipCustomInstructions,omitempty"` + // Optional path for trajectory output. + TrajectoryFile *string `json:"trajectoryFile,omitempty"` + // Absolute working-directory path for shell tools. + WorkingDirectory *string `json:"workingDirectory,omitempty"` +} + +// Indicates whether the session options patch was applied successfully. +// Experimental: SessionUpdateOptionsResult is part of an experimental API and may change or +// be removed. +type SessionUpdateOptionsResult struct { + // Whether the operation succeeded + Success bool `json:"success"` +} + +// Updated working directory and git context. Emitted as the new payload of +// `session.context_changed`. +// Experimental: SessionWorkingDirectoryContext is part of an experimental API and may +// change or be removed. +type SessionWorkingDirectoryContext struct { + // Merge-base commit SHA (fork point from the remote default branch) + BaseCommit *string `json:"baseCommit,omitempty"` + // Current git branch name + Branch *string `json:"branch,omitempty"` + // Current working directory path + Cwd string `json:"cwd"` + // Root directory of the git repository, resolved via git rev-parse + GitRoot *string `json:"gitRoot,omitempty"` + // Head commit of the current git branch + HeadCommit *string `json:"headCommit,omitempty"` + // Hosting platform type of the repository + HostType *SessionWorkingDirectoryContextHostType `json:"hostType,omitempty"` + // Repository identifier derived from the git remote URL ("owner/name" for GitHub, + // "org/project/repo" for Azure DevOps) + Repository *string `json:"repository,omitempty"` + // Raw host string from the git remote URL (e.g. "github.com", "dev.azure.com") + RepositoryHost *string `json:"repositoryHost,omitempty"` } type SessionWorkspacesCreateFileResult struct { @@ -1865,6 +3918,15 @@ type ShellKillResult struct { Killed bool `json:"killed"` } +// Parameters for shutting down the session +type ShutdownRequest struct { + // Optional human-readable reason. Typically the message of the error that triggered + // shutdown when type is 'error'. + Reason *string `json:"reason,omitempty"` + // Why the session is being shut down. Defaults to "routine" when omitted. + Type *ShutdownType `json:"type,omitempty"` +} + // Schema for the `Skill` type. // Experimental: Skill is part of an experimental API and may change or be removed. type Skill struct { @@ -1876,6 +3938,8 @@ type Skill struct { Name string `json:"name"` // Absolute path to the skill file Path *string `json:"path,omitempty"` + // Name of the plugin that provides the skill, when source is 'plugin' + PluginName *string `json:"pluginName,omitempty"` // Source location type (e.g., project, personal-copilot, plugin, builtin) Source SkillSource `json:"source"` // Whether the skill can be invoked by the user as a slash command @@ -1922,6 +3986,30 @@ type SkillsEnableRequest struct { Name string `json:"name"` } +// Skills invoked during this session, ordered by invocation time (most recent last). +// Experimental: SkillsGetInvokedResult is part of an experimental API and may change or be +// removed. +type SkillsGetInvokedResult struct { + // Skills invoked during this session, ordered by invocation time (most recent last) + Skills []SkillsInvokedSkill `json:"skills"` +} + +// Schema for the `SkillsInvokedSkill` type. +// Experimental: SkillsInvokedSkill is part of an experimental API and may change or be +// removed. +type SkillsInvokedSkill struct { + // Tools that should be auto-approved when this skill is active, captured at invocation time + AllowedTools []string `json:"allowedTools,omitempty"` + // Full content of the skill file + Content string `json:"content"` + // Turn number when the skill was invoked + InvokedAtTurn int64 `json:"invokedAtTurn"` + // Unique identifier for the skill + Name string `json:"name"` + // Path to the SKILL.md file + Path string `json:"path"` +} + // Diagnostics from reloading skill definitions, with warnings and errors as separate lists. // Experimental: SkillsLoadDiagnostics is part of an experimental API and may change or be // removed. @@ -2032,6 +4120,55 @@ func (SlashCommandTextResult) Kind() SlashCommandInvocationResultKind { return SlashCommandInvocationResultKindText } +// Schema for the `TaskAgentProgress` type. +// Experimental: TaskAgentProgress is part of an experimental API and may change or be +// removed. +type TaskAgentProgress interface { + taskAgentProgress() + Type() TaskAgentProgressType +} + +type RawTaskAgentProgressData struct { + Discriminator TaskAgentProgressType + Raw json.RawMessage +} + +func (RawTaskAgentProgressData) taskAgentProgress() {} +func (r RawTaskAgentProgressData) Type() TaskAgentProgressType { + return r.Discriminator +} + +type TaskAgentProgressAgent struct { + // The most recent intent reported by the agent + LatestIntent *string `json:"latestIntent,omitempty"` + // Recent tool execution events converted to display lines + RecentActivity []TaskAgentProgressAgentRecentActivityItem `json:"recentActivity"` +} + +func (TaskAgentProgressAgent) taskAgentProgress() {} +func (TaskAgentProgressAgent) Type() TaskAgentProgressType { + return TaskAgentProgressTypeAgent +} + +type TaskAgentProgressShell struct { + // Process ID when available + Pid *int64 `json:"pid,omitempty"` + // Recent stdout/stderr lines from the running shell command + RecentOutput string `json:"recentOutput"` +} + +func (TaskAgentProgressShell) taskAgentProgress() {} +func (TaskAgentProgressShell) Type() TaskAgentProgressType { + return TaskAgentProgressTypeShell +} + +type TaskAgentProgressAgentRecentActivityItem struct { + // Display message, e.g., "▸ bash", "✓ edit src/foo.ts" + Message string `json:"message"` + // ISO 8601 timestamp when this event occurred + Timestamp time.Time `json:"timestamp"` +} + // Schema for the `TaskInfo` type. // Experimental: TaskInfo is part of an experimental API and may change or be removed. type TaskInfo interface { @@ -2135,6 +4272,14 @@ type TaskList struct { Tasks []TaskInfo `json:"tasks"` } +// Progress information for the task, discriminated by type. Returns null when no task with +// this ID is currently tracked. +// Experimental: TaskProgress is part of an experimental API and may change or be removed. +type TaskProgress struct { + TaskAgentProgress TaskAgentProgress + TaskShellProgress *any +} + // Identifier of the background task to cancel. // Experimental: TasksCancelRequest is part of an experimental API and may change or be // removed. @@ -2151,6 +4296,49 @@ type TasksCancelResult struct { Cancelled bool `json:"cancelled"` } +// The first sync-waiting task that can currently be promoted to background mode. +// Experimental: TasksGetCurrentPromotableResult is part of an experimental API and may +// change or be removed. +type TasksGetCurrentPromotableResult struct { + // The first sync-waiting task (agent first, then shell) that can currently be promoted to + // background mode. Omitted if no such task exists. The returned task is guaranteed to have + // executionMode='sync' and canPromoteToBackground=true at the time of the call. + Task TaskInfo `json:"task,omitempty"` +} + +// Identifier of the background task to fetch progress for. +// Experimental: TasksGetProgressRequest is part of an experimental API and may change or be +// removed. +type TasksGetProgressRequest struct { + // Task identifier (agent ID or shell ID) + ID string `json:"id"` +} + +// Progress information for the task, or null when no task with that ID is tracked. +// Experimental: TasksGetProgressResult is part of an experimental API and may change or be +// removed. +type TasksGetProgressResult struct { + // Progress information for the task, discriminated by type. Returns null when no task with + // this ID is currently tracked. + Progress *TaskProgress `json:"progress,omitempty"` +} + +// Schema for the `TaskShellProgress` type. +// Experimental: TaskShellProgress is part of an experimental API and may change or be +// removed. +type TaskShellProgress any + +// The promoted task as it now exists in background mode, omitted if no promotable task was +// waiting. +// Experimental: TasksPromoteCurrentToBackgroundResult is part of an experimental API and +// may change or be removed. +type TasksPromoteCurrentToBackgroundResult struct { + // The promoted task as it now exists in background mode, omitted if no promotable task was + // waiting. Atomic operation: avoids the race window of getCurrentPromotable + + // promoteToBackground. + Task TaskInfo `json:"task,omitempty"` +} + // Identifier of the task to promote to background mode. // Experimental: TasksPromoteToBackgroundRequest is part of an experimental API and may // change or be removed. @@ -2167,6 +4355,13 @@ type TasksPromoteToBackgroundResult struct { Promoted bool `json:"promoted"` } +// Refresh metadata for any detached background shells the runtime knows about. Use after a +// long pause to pick up exit/output state for shells running outside the agent loop. +// Experimental: TasksRefreshResult is part of an experimental API and may change or be +// removed. +type TasksRefreshResult struct { +} + // Identifier of the completed or cancelled task to remove from tracking. // Experimental: TasksRemoveRequest is part of an experimental API and may change or be // removed. @@ -2231,6 +4426,25 @@ type TasksStartAgentResult struct { AgentID string `json:"agentId"` } +// Wait until all in-flight background tasks (agents + shells) and any follow-up turns +// scheduled by their completions have settled. Returns when the runtime is fully drained or +// after an internal timeout (default 10 minutes; configurable via +// COPILOT_TASK_WAIT_TIMEOUT_SECONDS). +// Experimental: TasksWaitForPendingResult is part of an experimental API and may change or +// be removed. +type TasksWaitForPendingResult struct { +} + +// Feature override key/value pairs to attach to subsequent telemetry events from this +// session. +// Experimental: TelemetrySetFeatureOverridesRequest is part of an experimental API and may +// change or be removed. +type TelemetrySetFeatureOverridesRequest struct { + // Override key/value pairs to attach to subsequent telemetry events from this session. + // Replaces any previously-set overrides. + Features map[string]string `json:"features"` +} + // Schema for the `Tool` type. type Tool struct { // Description of what the tool does @@ -2252,6 +4466,12 @@ type ToolList struct { Tools []Tool `json:"tools"` } +// Resolve, build, and validate the runtime tool list for this session. Subagent sessions +// and consumer flows that need an initialized tool set before `send` invoke this. Default +// base-class implementation is a no-op for sessions that don't support tool validation. +type ToolsInitializeAndValidateResult struct { +} + // Optional model identifier whose tool overrides should be applied to the listing. type ToolsListRequest struct { // Optional model ID — when provided, the returned tool list reflects model-specific @@ -2364,9 +4584,9 @@ type UIElicitationArrayAnyOfField struct { // Schema applied to each item in the array. Items UIElicitationArrayAnyOfFieldItems `json:"items"` // Maximum number of items the user may select. - MaxItems *float64 `json:"maxItems,omitempty"` + MaxItems *int64 `json:"maxItems,omitempty"` // Minimum number of items the user must select. - MinItems *float64 `json:"minItems,omitempty"` + MinItems *int64 `json:"minItems,omitempty"` // Human-readable label for the field. Title *string `json:"title,omitempty"` } @@ -2385,9 +4605,9 @@ type UIElicitationArrayEnumField struct { // Schema applied to each item in the array. Items UIElicitationArrayEnumFieldItems `json:"items"` // Maximum number of items the user may select. - MaxItems *float64 `json:"maxItems,omitempty"` + MaxItems *int64 `json:"maxItems,omitempty"` // Minimum number of items the user must select. - MinItems *float64 `json:"minItems,omitempty"` + MinItems *int64 `json:"minItems,omitempty"` // Human-readable label for the field. Title *string `json:"title,omitempty"` } @@ -2444,9 +4664,9 @@ type UIElicitationSchemaPropertyString struct { // Optional format hint that constrains the accepted input. Format *UIElicitationSchemaPropertyStringFormat `json:"format,omitempty"` // Maximum number of characters allowed. - MaxLength *float64 `json:"maxLength,omitempty"` + MaxLength *int64 `json:"maxLength,omitempty"` // Minimum number of characters required. - MinLength *float64 `json:"minLength,omitempty"` + MinLength *int64 `json:"minLength,omitempty"` // Human-readable label for the field. Title *string `json:"title,omitempty"` } @@ -2500,6 +4720,28 @@ type UIElicitationStringOneOfFieldOneOf struct { Title string `json:"title"` } +// Schema for the `UIExitPlanModeResponse` type. +type UIExitPlanModeResponse struct { + // Whether the plan was approved. + Approved bool `json:"approved"` + // Whether subsequent edits should be auto-approved without confirmation. + AutoApproveEdits *bool `json:"autoApproveEdits,omitempty"` + // Feedback from the user when they declined the plan or requested changes. + Feedback *string `json:"feedback,omitempty"` + // The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, + // otherwise 'interactive'. + SelectedAction *UIExitPlanModeAction `json:"selectedAction,omitempty"` +} + +// Request ID of a pending `auto_mode_switch.requested` event and the user's response. +type UIHandlePendingAutoModeSwitchRequest struct { + // The unique request ID from the auto_mode_switch.requested event + RequestID string `json:"requestId"` + // User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist + // as setting), or no (decline). + Response UIAutoModeSwitchResponse `json:"response"` +} + // Pending elicitation request ID and the user's response (accept/decline/cancel + form // values). type UIHandlePendingElicitationRequest struct { @@ -2509,6 +4751,79 @@ type UIHandlePendingElicitationRequest struct { Result UIElicitationResponse `json:"result"` } +// Request ID of a pending `exit_plan_mode.requested` event and the user's response. +type UIHandlePendingExitPlanModeRequest struct { + // The unique request ID from the exit_plan_mode.requested event + RequestID string `json:"requestId"` + // Schema for the `UIExitPlanModeResponse` type. + Response UIExitPlanModeResponse `json:"response"` +} + +// Indicates whether the pending UI request was resolved by this call. +type UIHandlePendingResult struct { + // True if the request was still pending and was resolved by this call. False if the request + // ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise + // no longer pending. + Success bool `json:"success"` +} + +// Request ID of a pending `sampling.requested` event and an optional sampling result +// payload (omit to reject). +type UIHandlePendingSamplingRequest struct { + // The unique request ID from the sampling.requested event + RequestID string `json:"requestId"` + // Optional sampling result payload. Omit to reject/cancel the sampling request without + // providing a result. + Response *UIHandlePendingSamplingResponse `json:"response,omitempty"` +} + +// Optional sampling result payload. Omit to reject/cancel the sampling request without +// providing a result. +type UIHandlePendingSamplingResponse struct { +} + +// Request ID of a pending `user_input.requested` event and the user's response. +type UIHandlePendingUserInputRequest struct { + // The unique request ID from the user_input.requested event + RequestID string `json:"requestId"` + // Schema for the `UIUserInputResponse` type. + Response UIUserInputResponse `json:"response"` +} + +// Register an in-process handler for `auto_mode_switch.requested` events. The caller still +// attaches the actual listener via the standard event-subscription mechanism; this +// registration solely tells the server bridge to skip its own dispatch (so a remote client +// doesn't race the in-process handler for the same requestId). +type UIRegisterDirectAutoModeSwitchHandlerResult struct { + // Opaque handle representing the registration. Pass this same handle to + // `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. + // Multiple registrations are reference-counted; the server bridge will only dispatch + // auto-mode-switch requests when no handles are active. + Handle string `json:"handle"` +} + +// Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. +type UIUnregisterDirectAutoModeSwitchHandlerRequest struct { + // Handle previously returned by `registerDirectAutoModeSwitchHandler` + Handle string `json:"handle"` +} + +// Indicates whether the handle was active and the registration count was decremented. +type UIUnregisterDirectAutoModeSwitchHandlerResult struct { + // True if the handle was active and decremented the counter; false if the handle was + // unknown. + Unregistered bool `json:"unregistered"` +} + +// Schema for the `UIUserInputResponse` type. +type UIUserInputResponse struct { + // The user's answer text + Answer string `json:"answer"` + // True if the user typed a freeform response, false if they selected a presented choice. + // Used by telemetry to differentiate between free text input and choice selection. + WasFreeform bool `json:"wasFreeform"` +} + // Accumulated session usage metrics, including premium request cost, token counts, model // breakdown, and code-change totals. // Experimental: UsageGetMetricsResult is part of an experimental API and may change or be @@ -2524,12 +4839,12 @@ type UsageGetMetricsResult struct { 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"` + // ISO 8601 timestamp when the session started + SessionStartTime time.Time `json:"sessionStartTime"` // Session-wide per-token-type accumulated token counts TokenDetails map[string]UsageMetricsTokenDetail `json:"tokenDetails,omitempty"` // Total time spent in model API calls (milliseconds) - TotalAPIDurationMs float64 `json:"totalApiDurationMs"` + TotalAPIDurationMs int64 `json:"totalApiDurationMs"` // Session-wide accumulated nano-AI units cost TotalNanoAiu *int64 `json:"totalNanoAiu,omitempty"` // Total user-initiated premium request cost across all models (may be fractional due to @@ -2543,6 +4858,8 @@ type UsageGetMetricsResult struct { // Experimental: UsageMetricsCodeChanges is part of an experimental API and may change or be // removed. type UsageMetricsCodeChanges struct { + // Distinct file paths modified during the session + FilesModified []string `json:"filesModified"` // Number of distinct files modified FilesModifiedCount int64 `json:"filesModifiedCount"` // Total lines of code added @@ -2607,6 +4924,116 @@ type UsageMetricsTokenDetail struct { TokenCount int64 `json:"tokenCount"` } +// The approval to add as a session-scoped rule +type UserToolSessionApproval interface { + userToolSessionApproval() + Kind() UserToolSessionApprovalKind +} + +type RawUserToolSessionApprovalData struct { + Discriminator UserToolSessionApprovalKind + Raw json.RawMessage +} + +func (RawUserToolSessionApprovalData) userToolSessionApproval() {} +func (r RawUserToolSessionApprovalData) Kind() UserToolSessionApprovalKind { + return r.Discriminator +} + +// Schema for the `UserToolSessionApprovalCommands` type. +type UserToolSessionApprovalCommands struct { + // Command identifiers approved by the user + CommandIdentifiers []string `json:"commandIdentifiers"` +} + +func (UserToolSessionApprovalCommands) userToolSessionApproval() {} +func (UserToolSessionApprovalCommands) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindCommands +} + +// Schema for the `UserToolSessionApprovalCustomTool` type. +type UserToolSessionApprovalCustomTool struct { + // Custom tool name + ToolName string `json:"toolName"` +} + +func (UserToolSessionApprovalCustomTool) userToolSessionApproval() {} +func (UserToolSessionApprovalCustomTool) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindCustomTool +} + +// Schema for the `UserToolSessionApprovalExtensionManagement` type. +type UserToolSessionApprovalExtensionManagement struct { + // Optional operation identifier + Operation *string `json:"operation,omitempty"` +} + +func (UserToolSessionApprovalExtensionManagement) userToolSessionApproval() {} +func (UserToolSessionApprovalExtensionManagement) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindExtensionManagement +} + +// Schema for the `UserToolSessionApprovalExtensionPermissionAccess` type. +type UserToolSessionApprovalExtensionPermissionAccess struct { + // Extension name + ExtensionName string `json:"extensionName"` +} + +func (UserToolSessionApprovalExtensionPermissionAccess) userToolSessionApproval() {} +func (UserToolSessionApprovalExtensionPermissionAccess) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindExtensionPermissionAccess +} + +// Schema for the `UserToolSessionApprovalMcp` type. +type UserToolSessionApprovalMcp struct { + // MCP server name + ServerName string `json:"serverName"` + // Optional MCP tool name, or null for all tools on the server + ToolName *string `json:"toolName"` +} + +func (UserToolSessionApprovalMcp) userToolSessionApproval() {} +func (UserToolSessionApprovalMcp) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindMcp +} + +// Schema for the `UserToolSessionApprovalMemory` type. +type UserToolSessionApprovalMemory struct { +} + +func (UserToolSessionApprovalMemory) userToolSessionApproval() {} +func (UserToolSessionApprovalMemory) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindMemory +} + +// Schema for the `UserToolSessionApprovalRead` type. +type UserToolSessionApprovalRead struct { +} + +func (UserToolSessionApprovalRead) userToolSessionApproval() {} +func (UserToolSessionApprovalRead) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindRead +} + +// Schema for the `UserToolSessionApprovalWrite` type. +type UserToolSessionApprovalWrite struct { +} + +func (UserToolSessionApprovalWrite) userToolSessionApproval() {} +func (UserToolSessionApprovalWrite) Kind() UserToolSessionApprovalKind { + return UserToolSessionApprovalKindWrite +} + +// Schema for the `WorkspacesCheckpoints` type. +type WorkspacesCheckpoints struct { + // Filename of the checkpoint within the workspace checkpoints directory + Filename string `json:"filename"` + // Checkpoint number assigned by the workspace manager + Number int64 `json:"number"` + // Human-readable checkpoint title + Title string `json:"title"` +} + // Relative path and UTF-8 content for the workspace file to create or overwrite. type WorkspacesCreateFileRequest struct { // File content to write as a UTF-8 string @@ -2615,8 +5042,12 @@ type WorkspacesCreateFileRequest struct { Path string `json:"path"` } -// Current workspace metadata for the session, or null when not available. +// Current workspace metadata for the session, including its absolute filesystem path when +// available. type WorkspacesGetWorkspaceResult struct { + // Absolute filesystem path to the workspace directory. Omitted when the session has no + // workspace (e.g. remote sessions). + Path *string `json:"path,omitempty"` // Current workspace metadata, or null if not available Workspace *WorkspacesGetWorkspaceResultWorkspace `json:"workspace"` } @@ -2640,12 +5071,30 @@ type WorkspacesGetWorkspaceResultWorkspace struct { UserNamed *bool `json:"user_named,omitempty"` } +// Workspace checkpoints in chronological order; empty when the workspace is not enabled. +type WorkspacesListCheckpointsResult struct { + // Workspace checkpoints in chronological order. Empty when workspace is not enabled. + Checkpoints []WorkspacesCheckpoints `json:"checkpoints"` +} + // Relative paths of files stored in the session workspace files directory. type WorkspacesListFilesResult struct { // Relative file paths in the workspace files directory Files []string `json:"files"` } +// Checkpoint number to read. +type WorkspacesReadCheckpointRequest struct { + // Checkpoint number to read + Number int64 `json:"number"` +} + +// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. +type WorkspacesReadCheckpointResult struct { + // Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing + Content *string `json:"content"` +} + // Relative path of the workspace file to read. type WorkspacesReadFileRequest struct { // Relative path within the workspace files directory @@ -2658,7 +5107,75 @@ type WorkspacesReadFileResult struct { Content string `json:"content"` } -// Authentication type +// Pasted content to save as a UTF-8 file in the session workspace. +type WorkspacesSaveLargePasteRequest struct { + // Pasted content to save as a UTF-8 file + Content string `json:"content"` +} + +// Descriptor for the saved paste file, or null when the workspace is unavailable. +type WorkspacesSaveLargePasteResult struct { + // Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, + // non-infinite sessions, remote sessions) + Saved *WorkspacesSaveLargePasteResultSaved `json:"saved"` +} + +type WorkspacesSaveLargePasteResultSaved struct { + // Filename within the workspace files directory + Filename string `json:"filename"` + // Absolute filesystem path to the saved paste file + FilePath string `json:"filePath"` + // Size of the saved file in bytes + SizeBytes int64 `json:"sizeBytes"` +} + +// Public-facing projection of workspace metadata for SDK / TUI consumers +// Experimental: WorkspaceSummary is part of an experimental API and may change or be +// removed. +type WorkspaceSummary struct { + // Branch checked out at session start, if any + Branch *string `json:"branch,omitempty"` + // ISO 8601 timestamp when the workspace was created + CreatedAt *time.Time `json:"created_at,omitempty"` + // Current working directory at session start + Cwd *string `json:"cwd,omitempty"` + // Resolved git root for cwd, if any + GitRoot *string `json:"git_root,omitempty"` + // Repository host type, if known + HostType *WorkspaceSummaryHostType `json:"host_type,omitempty"` + // Workspace identifier (1:1 with sessionId) + ID string `json:"id"` + // Display name for the session, if set + Name *string `json:"name,omitempty"` + // Repository identifier in 'owner/repo' or 'org/project/repo' format, if any + Repository *string `json:"repository,omitempty"` + // ISO 8601 timestamp when the workspace was last updated + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +// Finite reason code describing why the current turn was aborted +type AbortReason string + +const ( + AbortReasonRemoteCommand AbortReason = "remote_command" + AbortReasonUserAbort AbortReason = "user_abort" + AbortReasonUserInitiated AbortReason = "user_initiated" +) + +// Where the agent definition was loaded from +// Experimental: AgentInfoSource is part of an experimental API and may change or be removed. +type AgentInfoSource string + +const ( + AgentInfoSourceBuiltin AgentInfoSource = "builtin" + AgentInfoSourceInherited AgentInfoSource = "inherited" + AgentInfoSourcePlugin AgentInfoSource = "plugin" + AgentInfoSourceProject AgentInfoSource = "project" + AgentInfoSourceRemote AgentInfoSource = "remote" + AgentInfoSourceUser AgentInfoSource = "user" +) + +// Type discriminator for AuthInfo. type AuthInfoType string const ( @@ -2692,6 +5209,13 @@ const ( ContentFilterModeNone ContentFilterMode = "none" ) +// Authentication host (always the public GitHub host). +type CopilotAPITokenAuthInfoHost string + +const ( + CopilotAPITokenAuthInfoHostHTTPSGithubCom CopilotAPITokenAuthInfoHost = "https://github.com" +) + // Server transport type: stdio, http, sse, or memory type DiscoveredMcpServerType string @@ -2702,6 +5226,37 @@ const ( DiscoveredMcpServerTypeStdio DiscoveredMcpServerType = "stdio" ) +type EventLogTypesString string + +const ( + EventLogTypesStringValue EventLogTypesString = "*" +) + +// Agent-scope filter: 'primary' returns only main-agent events plus events whose type +// starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns +// events from all agents (matching wildcard-subscription behavior). Default is 'all' to +// preserve wildcard semantics for catch-up callers. +// Experimental: EventsAgentScope is part of an experimental API and may change or be +// removed. +type EventsAgentScope string + +const ( + EventsAgentScopeAll EventsAgentScope = "all" + EventsAgentScopePrimary EventsAgentScope = "primary" +) + +// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor +// referred to an event that no longer exists in history (e.g. truncated or compacted away) +// and the read started from the beginning of the remaining history. +// Experimental: EventsCursorStatus is part of an experimental API and may change or be +// removed. +type EventsCursorStatus string + +const ( + EventsCursorStatusExpired EventsCursorStatus = "expired" + EventsCursorStatusOk EventsCursorStatus = "ok" +) + // Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) // Experimental: ExtensionSource is part of an experimental API and may change or be removed. type ExtensionSource string @@ -2751,27 +5306,70 @@ const ( ExternalToolTextResultForLlmContentTypeText ExternalToolTextResultForLlmContentType = "text" ) -// Where this source lives — used for UI grouping -type InstructionsSourcesLocation string +// Authentication host. HMAC auth always targets the public GitHub host. +type HMACAuthInfoHost string const ( - InstructionsSourcesLocationRepository InstructionsSourcesLocation = "repository" - InstructionsSourcesLocationUser InstructionsSourcesLocation = "user" - InstructionsSourcesLocationWorkingDirectory InstructionsSourcesLocation = "working-directory" + HMACAuthInfoHostHTTPSGithubCom HMACAuthInfoHost = "https://github.com" ) -// Category of instruction source — used for merge logic -type InstructionsSourcesType string +// Constant value. Always "github". +type InstalledPluginSourceGithubSource string const ( - InstructionsSourcesTypeChildInstructions InstructionsSourcesType = "child-instructions" - InstructionsSourcesTypeHome InstructionsSourcesType = "home" - InstructionsSourcesTypeModel InstructionsSourcesType = "model" - InstructionsSourcesTypeNestedAgents InstructionsSourcesType = "nested-agents" + InstalledPluginSourceGithubSourceGithub InstalledPluginSourceGithubSource = "github" +) + +// Constant value. Always "local". +type InstalledPluginSourceLocalSource string + +const ( + InstalledPluginSourceLocalSourceLocal InstalledPluginSourceLocalSource = "local" +) + +// Constant value. Always "url". +type InstalledPluginSourceURLSource string + +const ( + InstalledPluginSourceURLSourceURL InstalledPluginSourceURLSource = "url" +) + +// Where this source lives — used for UI grouping +type InstructionsSourcesLocation string + +const ( + InstructionsSourcesLocationPlugin InstructionsSourcesLocation = "plugin" + InstructionsSourcesLocationRepository InstructionsSourcesLocation = "repository" + InstructionsSourcesLocationUser InstructionsSourcesLocation = "user" + InstructionsSourcesLocationWorkingDirectory InstructionsSourcesLocation = "working-directory" +) + +// Category of instruction source — used for merge logic +type InstructionsSourcesType string + +const ( + InstructionsSourcesTypeChildInstructions InstructionsSourcesType = "child-instructions" + InstructionsSourcesTypeHome InstructionsSourcesType = "home" + InstructionsSourcesTypeModel InstructionsSourcesType = "model" + InstructionsSourcesTypeNestedAgents InstructionsSourcesType = "nested-agents" + InstructionsSourcesTypePlugin InstructionsSourcesType = "plugin" InstructionsSourcesTypeRepo InstructionsSourcesType = "repo" InstructionsSourcesTypeVscode InstructionsSourcesType = "vscode" ) +// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered +// an error (including agent-side rejection by content filter or criteria); 'cancelled' the +// caller cancelled this execution via cancelSamplingExecution. +// Experimental: McpSamplingExecutionAction is part of an experimental API and may change or +// be removed. +type McpSamplingExecutionAction string + +const ( + McpSamplingExecutionActionCancelled McpSamplingExecutionAction = "cancelled" + McpSamplingExecutionActionFailure McpSamplingExecutionAction = "failure" + McpSamplingExecutionActionSuccess McpSamplingExecutionAction = "success" +) + // OAuth grant type to use when authenticating to the remote MCP server. type McpServerConfigHTTPOauthGrantType string @@ -2811,6 +5409,42 @@ const ( McpServerStatusPending McpServerStatus = "pending" ) +// How environment-variable values supplied to MCP servers are resolved. "direct" passes +// literal string values; "indirect" treats values as references (e.g. names of environment +// variables on the host) that the runtime resolves before launch. Defaults to the runtime's +// startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI +// prompt mode and ACP) set this to "direct". +// Experimental: McpSetEnvValueModeDetails is part of an experimental API and may change or +// be removed. +type McpSetEnvValueModeDetails string + +const ( + McpSetEnvValueModeDetailsDirect McpSetEnvValueModeDetails = "direct" + McpSetEnvValueModeDetailsIndirect McpSetEnvValueModeDetails = "indirect" +) + +// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') +// Experimental: MetadataSnapshotCurrentMode is part of an experimental API and may change +// or be removed. +type MetadataSnapshotCurrentMode string + +const ( + MetadataSnapshotCurrentModeAutopilot MetadataSnapshotCurrentMode = "autopilot" + MetadataSnapshotCurrentModeInteractive MetadataSnapshotCurrentMode = "interactive" + MetadataSnapshotCurrentModePlan MetadataSnapshotCurrentMode = "plan" +) + +// Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` +// invocation. +// Experimental: MetadataSnapshotRemoteMetadataTaskType is part of an experimental API and +// may change or be removed. +type MetadataSnapshotRemoteMetadataTaskType string + +const ( + MetadataSnapshotRemoteMetadataTaskTypeCca MetadataSnapshotRemoteMetadataTaskType = "cca" + MetadataSnapshotRemoteMetadataTaskTypeCli MetadataSnapshotRemoteMetadataTaskType = "cli" +) + // Model capability category for grouping in the model picker type ModelPickerCategory string @@ -2839,6 +5473,17 @@ const ( ModelPolicyStateUnconfigured ModelPolicyState = "unconfigured" ) +// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` +// resolves at launch). +// Experimental: OptionsUpdateEnvValueMode is part of an experimental API and may change or +// be removed. +type OptionsUpdateEnvValueMode string + +const ( + OptionsUpdateEnvValueModeDirect OptionsUpdateEnvValueMode = "direct" + OptionsUpdateEnvValueModeIndirect OptionsUpdateEnvValueMode = "indirect" +) + // Kind discriminator for PermissionDecisionApproveForLocationApproval. type PermissionDecisionApproveForLocationApprovalKind string @@ -2873,12 +5518,59 @@ const ( type PermissionDecisionKind string const ( - PermissionDecisionKindApproveForLocation PermissionDecisionKind = "approve-for-location" - PermissionDecisionKindApproveForSession PermissionDecisionKind = "approve-for-session" - PermissionDecisionKindApproveOnce PermissionDecisionKind = "approve-once" - PermissionDecisionKindApprovePermanently PermissionDecisionKind = "approve-permanently" - PermissionDecisionKindReject PermissionDecisionKind = "reject" - PermissionDecisionKindUserNotAvailable PermissionDecisionKind = "user-not-available" + PermissionDecisionKindApproved PermissionDecisionKind = "approved" + PermissionDecisionKindApprovedForLocation PermissionDecisionKind = "approved-for-location" + PermissionDecisionKindApprovedForSession PermissionDecisionKind = "approved-for-session" + PermissionDecisionKindApproveForLocation PermissionDecisionKind = "approve-for-location" + PermissionDecisionKindApproveForSession PermissionDecisionKind = "approve-for-session" + PermissionDecisionKindApproveOnce PermissionDecisionKind = "approve-once" + PermissionDecisionKindApprovePermanently PermissionDecisionKind = "approve-permanently" + PermissionDecisionKindCancelled PermissionDecisionKind = "cancelled" + PermissionDecisionKindDeniedByContentExclusionPolicy PermissionDecisionKind = "denied-by-content-exclusion-policy" + PermissionDecisionKindDeniedByPermissionRequestHook PermissionDecisionKind = "denied-by-permission-request-hook" + PermissionDecisionKindDeniedByRules PermissionDecisionKind = "denied-by-rules" + PermissionDecisionKindDeniedInteractivelyByUser PermissionDecisionKind = "denied-interactively-by-user" + PermissionDecisionKindDeniedNoApprovalRuleAndCouldNotRequestFromUser PermissionDecisionKind = "denied-no-approval-rule-and-could-not-request-from-user" + PermissionDecisionKindReject PermissionDecisionKind = "reject" + PermissionDecisionKindUserNotAvailable PermissionDecisionKind = "user-not-available" +) + +// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` +// enumeration. +type PermissionsConfigureAdditionalContentExclusionPolicyScope string + +const ( + PermissionsConfigureAdditionalContentExclusionPolicyScopeAll PermissionsConfigureAdditionalContentExclusionPolicyScope = "all" + PermissionsConfigureAdditionalContentExclusionPolicyScopeRepo PermissionsConfigureAdditionalContentExclusionPolicyScope = "repo" +) + +// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or +// to location-scoped rules persisted via the location-permissions config file. +type PermissionsModifyRulesScope string + +const ( + PermissionsModifyRulesScopeLocation PermissionsModifyRulesScope = "location" + PermissionsModifyRulesScopeSession PermissionsModifyRulesScope = "session" +) + +// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. +type PermissionsSetApproveAllSource string + +const ( + PermissionsSetApproveAllSourceAutopilotConfirmation PermissionsSetApproveAllSource = "autopilot_confirmation" + PermissionsSetApproveAllSourceCliFlag PermissionsSetApproveAllSource = "cli_flag" + PermissionsSetApproveAllSourceRPC PermissionsSetApproveAllSource = "rpc" + PermissionsSetApproveAllSourceSlashCommand PermissionsSetApproveAllSource = "slash_command" +) + +// Whether this item is a queued user message or a queued slash command / model change +// Experimental: QueuePendingItemsKind is part of an experimental API and may change or be +// removed. +type QueuePendingItemsKind string + +const ( + QueuePendingItemsKindCommand QueuePendingItemsKind = "command" + QueuePendingItemsKindMessage QueuePendingItemsKind = "message" ) // Reasoning summary mode to request for supported model clients @@ -2902,6 +5594,56 @@ const ( RemoteSessionModeOn RemoteSessionMode = "on" ) +// The UI mode the agent was in when this message was sent. Defaults to the session's +// current mode. +type SendAgentMode string + +const ( + SendAgentModeAutopilot SendAgentMode = "autopilot" + SendAgentModeInteractive SendAgentMode = "interactive" + SendAgentModePlan SendAgentMode = "plan" + SendAgentModeShell SendAgentMode = "shell" +) + +// Type of GitHub reference +type SendAttachmentGithubReferenceType string + +const ( + SendAttachmentGithubReferenceTypeDiscussion SendAttachmentGithubReferenceType = "discussion" + SendAttachmentGithubReferenceTypeIssue SendAttachmentGithubReferenceType = "issue" + SendAttachmentGithubReferenceTypePr SendAttachmentGithubReferenceType = "pr" +) + +// Type discriminator for SendAttachment. +type SendAttachmentType string + +const ( + SendAttachmentTypeBlob SendAttachmentType = "blob" + SendAttachmentTypeDirectory SendAttachmentType = "directory" + SendAttachmentTypeFile SendAttachmentType = "file" + SendAttachmentTypeGithubReference SendAttachmentType = "github_reference" + SendAttachmentTypeSelection SendAttachmentType = "selection" +) + +// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` +// interjects during an in-progress turn. +type SendMode string + +const ( + SendModeEnqueue SendMode = "enqueue" + SendModeImmediate SendMode = "immediate" +) + +// Repository host type +// Experimental: SessionContextHostType is part of an experimental API and may change or be +// removed. +type SessionContextHostType string + +const ( + SessionContextHostTypeAdo SessionContextHostType = "ado" + SessionContextHostTypeGithub SessionContextHostType = "github" +) + // Error classification type SessionFsErrorCode string @@ -2936,6 +5678,27 @@ const ( SessionFsSqliteQueryTypeRun SessionFsSqliteQueryType = "run" ) +// Constant value. Always "github". +type SessionInstalledPluginSourceGithubSource string + +const ( + SessionInstalledPluginSourceGithubSourceGithub SessionInstalledPluginSourceGithubSource = "github" +) + +// Constant value. Always "local". +type SessionInstalledPluginSourceLocalSource string + +const ( + SessionInstalledPluginSourceLocalSourceLocal SessionInstalledPluginSourceLocalSource = "local" +) + +// Constant value. Always "url". +type SessionInstalledPluginSourceURLSource string + +const ( + SessionInstalledPluginSourceURLSourceURL SessionInstalledPluginSourceURLSource = "url" +) + // Log severity level. Determines how the message is displayed in the timeline. Defaults to // "info". type SessionLogLevel string @@ -2955,6 +5718,16 @@ const ( SessionModePlan SessionMode = "plan" ) +// Hosting platform type of the repository +// Experimental: SessionWorkingDirectoryContextHostType is part of an experimental API and +// may change or be removed. +type SessionWorkingDirectoryContextHostType string + +const ( + SessionWorkingDirectoryContextHostTypeAdo SessionWorkingDirectoryContextHostType = "ado" + SessionWorkingDirectoryContextHostTypeGithub SessionWorkingDirectoryContextHostType = "github" +) + // Signal to send (default: SIGTERM) type ShellKillSignal string @@ -2964,6 +5737,14 @@ const ( ShellKillSignalSIGTERM ShellKillSignal = "SIGTERM" ) +// Why the session is being shut down. Defaults to "routine" when omitted. +type ShutdownType string + +const ( + ShutdownTypeError ShutdownType = "error" + ShutdownTypeRoutine ShutdownType = "routine" +) + // Source location type (e.g., project, personal-copilot, plugin, builtin) type SkillSource string @@ -3003,6 +5784,14 @@ const ( SlashCommandKindSkill SlashCommandKind = "skill" ) +// Type discriminator for TaskAgentProgress. +type TaskAgentProgressType string + +const ( + TaskAgentProgressTypeAgent TaskAgentProgressType = "agent" + TaskAgentProgressTypeShell TaskAgentProgressType = "shell" +) + // Whether task execution is synchronously awaited or managed in the background // Experimental: TaskExecutionMode is part of an experimental API and may change or be // removed. @@ -3044,6 +5833,16 @@ const ( TaskStatusRunning TaskStatus = "running" ) +// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist +// as setting), or no (decline). +type UIAutoModeSwitchResponse string + +const ( + UIAutoModeSwitchResponseNo UIAutoModeSwitchResponse = "no" + UIAutoModeSwitchResponseYes UIAutoModeSwitchResponse = "yes" + UIAutoModeSwitchResponseYesAlways UIAutoModeSwitchResponse = "yes_always" +) + // Type discriminator. Always "string". type UIElicitationArrayEnumFieldItemsType string @@ -3096,6 +5895,31 @@ const ( UIElicitationSchemaTypeObject UIElicitationSchemaType = "object" ) +// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, +// otherwise 'interactive'. +type UIExitPlanModeAction string + +const ( + UIExitPlanModeActionAutopilot UIExitPlanModeAction = "autopilot" + UIExitPlanModeActionAutopilotFleet UIExitPlanModeAction = "autopilot_fleet" + UIExitPlanModeActionExitOnly UIExitPlanModeAction = "exit_only" + UIExitPlanModeActionInteractive UIExitPlanModeAction = "interactive" +) + +// Kind discriminator for UserToolSessionApproval. +type UserToolSessionApprovalKind string + +const ( + UserToolSessionApprovalKindCommands UserToolSessionApprovalKind = "commands" + UserToolSessionApprovalKindCustomTool UserToolSessionApprovalKind = "custom-tool" + UserToolSessionApprovalKindExtensionManagement UserToolSessionApprovalKind = "extension-management" + UserToolSessionApprovalKindExtensionPermissionAccess UserToolSessionApprovalKind = "extension-permission-access" + UserToolSessionApprovalKindMcp UserToolSessionApprovalKind = "mcp" + UserToolSessionApprovalKindMemory UserToolSessionApprovalKind = "memory" + UserToolSessionApprovalKindRead UserToolSessionApprovalKind = "read" + UserToolSessionApprovalKindWrite UserToolSessionApprovalKind = "write" +) + type WorkspacesGetWorkspaceResultWorkspaceHostType string const ( @@ -3103,6 +5927,14 @@ const ( WorkspacesGetWorkspaceResultWorkspaceHostTypeGithub WorkspacesGetWorkspaceResultWorkspaceHostType = "github" ) +// Repository host type, if known +type WorkspaceSummaryHostType string + +const ( + WorkspaceSummaryHostTypeAdo WorkspaceSummaryHostType = "ado" + WorkspaceSummaryHostTypeGithub WorkspaceSummaryHostType = "github" +) + type serverApi struct { client *jsonrpc2.Client } @@ -3307,938 +6139,2283 @@ func (a *ServerSessionFsApi) SetProvider(ctx context.Context, params *SessionFsS // Experimental: ServerSessionsApi contains experimental APIs that may change or be removed. type ServerSessionsApi serverApi -// Connects to an existing remote session and exposes it as an SDK session. +// BulkDelete closes, deactivates, and deletes a set of sessions, returning the bytes freed +// per session. // -// RPC method: sessions.connect. +// RPC method: sessions.bulkDelete. // -// Parameters: Remote session connection parameters. +// Parameters: Session IDs to close, deactivate, and delete from disk. // -// Returns: Remote session connection result. -func (a *ServerSessionsApi) Connect(ctx context.Context, params *ConnectRemoteSessionParams) (*RemoteSessionConnectionResult, error) { - raw, err := a.client.Request("sessions.connect", params) +// Returns: Map of sessionId -> bytes freed by removing the session's workspace directory. +func (a *ServerSessionsApi) BulkDelete(ctx context.Context, params *SessionsBulkDeleteRequest) (*SessionBulkDeleteResult, error) { + raw, err := a.client.Request("sessions.bulkDelete", params) if err != nil { return nil, err } - var result RemoteSessionConnectionResult + var result SessionBulkDeleteResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Fork creates a new session by forking persisted history from an existing session. +// CheckInUse returns the subset of the supplied session IDs that are currently held by +// another running process. // -// RPC method: sessions.fork. +// RPC method: sessions.checkInUse. // -// Parameters: Source session identifier to fork from, optional event-ID boundary, and -// optional friendly name for the new session. +// Parameters: Session IDs to test for live in-use locks. // -// Returns: Identifier and optional friendly name assigned to the newly forked session. -func (a *ServerSessionsApi) Fork(ctx context.Context, params *SessionsForkRequest) (*SessionsForkResult, error) { - raw, err := a.client.Request("sessions.fork", params) +// Returns: Session IDs from the input set that are currently in use by another process. +func (a *ServerSessionsApi) CheckInUse(ctx context.Context, params *SessionsCheckInUseRequest) (*SessionsCheckInUseResult, error) { + raw, err := a.client.Request("sessions.checkInUse", params) if err != nil { return nil, err } - var result SessionsForkResult + var result SessionsCheckInUseResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type ServerSkillsApi serverApi - -// Discovers skills across global and project sources. +// Closes a session: emits shutdown, flushes pending events, releases the in-use lock, and +// disposes the active session. // -// RPC method: skills.discover. +// RPC method: sessions.close. // -// Parameters: Optional project paths and additional skill directories to include in -// discovery. +// Parameters: Session ID to close. // -// Returns: Skills discovered across global and project sources. -func (a *ServerSkillsApi) Discover(ctx context.Context, params *SkillsDiscoverRequest) (*ServerSkillList, error) { - raw, err := a.client.Request("skills.discover", params) +// Returns: Closes a session: emits shutdown, flushes pending events to disk, releases the +// in-use lock, disposes the active session. Idempotent: succeeds even if the session is not +// currently active. +func (a *ServerSessionsApi) Close(ctx context.Context, params *SessionsCloseRequest) (*SessionsCloseResult, error) { + raw, err := a.client.Request("sessions.close", params) if err != nil { return nil, err } - var result ServerSkillList + var result SessionsCloseResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type ServerSkillsConfigApi serverApi - -// SetDisabledSkills replaces the global list of disabled skills. +// Connects to an existing remote session and exposes it as an SDK session. // -// RPC method: skills.config.setDisabledSkills. +// RPC method: sessions.connect. // -// Parameters: Skill names to mark as disabled in global configuration, replacing any -// previous list. -func (a *ServerSkillsConfigApi) SetDisabledSkills(ctx context.Context, params *SkillsConfigSetDisabledSkillsRequest) (*SkillsConfigSetDisabledSkillsResult, error) { - raw, err := a.client.Request("skills.config.setDisabledSkills", params) +// Parameters: Remote session connection parameters. +// +// Returns: Remote session connection result. +func (a *ServerSessionsApi) Connect(ctx context.Context, params *ConnectRemoteSessionParams) (*RemoteSessionConnectionResult, error) { + raw, err := a.client.Request("sessions.connect", params) if err != nil { return nil, err } - var result SkillsConfigSetDisabledSkillsResult + var result RemoteSessionConnectionResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func (s *ServerSkillsApi) Config() *ServerSkillsConfigApi { - return (*ServerSkillsConfigApi)(s) -} - -type ServerToolsApi serverApi - -// Lists built-in tools available for a model. +// EnrichMetadata backfills missing summary and context fields on the supplied session +// metadata records. // -// RPC method: tools.list. +// RPC method: sessions.enrichMetadata. // -// Parameters: Optional model identifier whose tool overrides should be applied to the -// listing. +// Parameters: Session metadata records to enrich with summary and context information. // -// Returns: Built-in tools available for the requested model, with their parameters and -// instructions. -func (a *ServerToolsApi) List(ctx context.Context, params *ToolsListRequest) (*ToolList, error) { - raw, err := a.client.Request("tools.list", params) +// Returns: The same metadata records, with summary and context fields backfilled where +// available. +func (a *ServerSessionsApi) EnrichMetadata(ctx context.Context, params *SessionsEnrichMetadataRequest) (*SessionEnrichMetadataResult, error) { + raw, err := a.client.Request("sessions.enrichMetadata", params) if err != nil { return nil, err } - var result ToolList + var result SessionEnrichMetadataResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// ServerRpc provides typed server-scoped RPC methods. -type ServerRpc struct { - // Reuse a single struct instead of allocating one for each service on the heap. - common serverApi - - Account *ServerAccountApi - Mcp *ServerMcpApi - Models *ServerModelsApi - SessionFs *ServerSessionFsApi - Sessions *ServerSessionsApi - Skills *ServerSkillsApi - Tools *ServerToolsApi -} - -// Ping checks server responsiveness and returns protocol information. +// FindByPrefix resolves a UUID prefix to a unique session ID, if exactly one session +// matches. // -// RPC method: ping. +// RPC method: sessions.findByPrefix. // -// Parameters: Optional message to echo back to the caller. +// Parameters: UUID prefix to resolve to a unique session ID. // -// Returns: Server liveness response, including the echoed message, current timestamp, and -// protocol version. -func (a *ServerRpc) Ping(ctx context.Context, params *PingRequest) (*PingResult, error) { - raw, err := a.common.client.Request("ping", params) +// Returns: Session ID matching the prefix, omitted when no unique match exists. +func (a *ServerSessionsApi) FindByPrefix(ctx context.Context, params *SessionsFindByPrefixRequest) (*SessionsFindByPrefixResult, error) { + raw, err := a.client.Request("sessions.findByPrefix", params) if err != nil { return nil, err } - var result PingResult + var result SessionsFindByPrefixResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { - r := &ServerRpc{} - r.common = serverApi{client: client} - r.Account = (*ServerAccountApi)(&r.common) - r.Mcp = (*ServerMcpApi)(&r.common) - r.Models = (*ServerModelsApi)(&r.common) - r.SessionFs = (*ServerSessionFsApi)(&r.common) - r.Sessions = (*ServerSessionsApi)(&r.common) - r.Skills = (*ServerSkillsApi)(&r.common) - r.Tools = (*ServerToolsApi)(&r.common) - return r -} - -type internalServerApi struct { - client *jsonrpc2.Client -} - -// InternalServerRpc provides internal SDK server-scoped RPC methods (handshake helpers -// etc.). Not part of the public API. -type InternalServerRpc struct { - // Reuse a single struct instead of allocating one for each service on the heap. - common internalServerApi -} - -// Connect performs the SDK server connection handshake and validates the optional -// connection token. +// FindByTaskId finds the local session bound to a GitHub task ID, if any. // -// RPC method: connect. +// RPC method: sessions.findByTaskId. // -// Parameters: Optional connection token presented by the SDK client during the handshake. +// Parameters: GitHub task ID to look up. // -// Returns: Handshake result reporting the server's protocol version and package version on -// success. -// Internal: Connect is part of the SDK's internal handshake/plumbing; external callers -// should not use it. -func (a *InternalServerRpc) Connect(ctx context.Context, params *ConnectRequest) (*ConnectResult, error) { - raw, err := a.common.client.Request("connect", params) +// Returns: ID of the local session bound to the given GitHub task, or omitted when none. +func (a *ServerSessionsApi) FindByTaskId(ctx context.Context, params *SessionsFindByTaskIDRequest) (*SessionsFindByTaskIDResult, error) { + raw, err := a.client.Request("sessions.findByTaskId", params) if err != nil { return nil, err } - var result ConnectResult + var result SessionsFindByTaskIDResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -func NewInternalServerRpc(client *jsonrpc2.Client) *InternalServerRpc { - r := &InternalServerRpc{} - r.common = internalServerApi{client: client} - return r -} - -type sessionApi struct { - client *jsonrpc2.Client - sessionID string -} - -// Experimental: AgentApi contains experimental APIs that may change or be removed. -type AgentApi sessionApi - -// Deselect clears the selected custom agent and returns the session to the default agent. +// Fork creates a new session by forking persisted history from an existing session. // -// RPC method: session.agent.deselect. -func (a *AgentApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.deselect", req) +// RPC method: sessions.fork. +// +// Parameters: Source session identifier to fork from, optional event-ID boundary, and +// optional friendly name for the new session. +// +// Returns: Identifier and optional friendly name assigned to the newly forked session. +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 } - var result SessionAgentDeselectResult + var result SessionsForkResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// GetCurrent gets the currently selected custom agent for the session. +// GetEventFilePath computes the absolute path to a session's persisted events.jsonl file. // -// RPC method: session.agent.getCurrent. +// RPC method: sessions.getEventFilePath. // -// Returns: The currently selected custom agent, or null when using the default agent. -func (a *AgentApi) GetCurrent(ctx context.Context) (*AgentGetCurrentResult, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.getCurrent", req) +// Parameters: Session ID whose event-log file path to compute. +// +// Returns: Absolute path to the session's events.jsonl file on disk. +func (a *ServerSessionsApi) GetEventFilePath(ctx context.Context, params *SessionsGetEventFilePathRequest) (*SessionsGetEventFilePathResult, error) { + raw, err := a.client.Request("sessions.getEventFilePath", params) if err != nil { return nil, err } - var result AgentGetCurrentResult + var result SessionsGetEventFilePathResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Lists custom agents available to the session. +// GetLastForContext returns the most-relevant prior session for a given working-directory +// context. // -// RPC method: session.agent.list. +// RPC method: sessions.getLastForContext. // -// Returns: Custom agents available to the session. -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) +// Parameters: Optional working-directory context used to score session relevance. +// +// Returns: Most-relevant session ID for the supplied context, or omitted when no sessions +// exist. +func (a *ServerSessionsApi) GetLastForContext(ctx context.Context, params *SessionsGetLastForContextRequest) (*SessionsGetLastForContextResult, error) { + raw, err := a.client.Request("sessions.getLastForContext", params) if err != nil { return nil, err } - var result AgentList + var result SessionsGetLastForContextResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Reloads custom agent definitions and returns the refreshed list. +// GetPersistedRemoteSteerable returns a session's persisted remote-steerable flag, if any +// has been recorded. // -// RPC method: session.agent.reload. +// RPC method: sessions.getPersistedRemoteSteerable. // -// Returns: Custom agents available to the session after reloading definitions from disk. -func (a *AgentApi) Reload(ctx context.Context) (*AgentReloadResult, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.agent.reload", req) +// Parameters: Session ID to look up the persisted remote-steerable flag for. +// +// Returns: The session's persisted remote-steerable flag, or omitted when no value has been +// persisted. +func (a *ServerSessionsApi) GetPersistedRemoteSteerable(ctx context.Context, params *SessionsGetPersistedRemoteSteerableRequest) (*SessionsGetPersistedRemoteSteerableResult, error) { + raw, err := a.client.Request("sessions.getPersistedRemoteSteerable", params) if err != nil { return nil, err } - var result AgentReloadResult + var result SessionsGetPersistedRemoteSteerableResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Selects a custom agent for subsequent turns in the session. -// -// RPC method: session.agent.select. +// GetSizes returns the on-disk byte size of each session's workspace directory. // -// Parameters: Name of the custom agent to select for subsequent turns. +// RPC method: sessions.getSizes. // -// Returns: The newly selected custom agent. -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 - } - raw, err := a.client.Request("session.agent.select", req) +// Returns: Map of sessionId -> on-disk size in bytes for each session's workspace directory. +func (a *ServerSessionsApi) GetSizes(ctx context.Context) (*SessionSizes, error) { + raw, err := a.client.Request("sessions.getSizes", nil) if err != nil { return nil, err } - var result AgentSelectResult + var result SessionSizes if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type AuthApi sessionApi - -// GetStatus gets authentication status and account metadata for the session. +// Lists persisted sessions, optionally filtered by working-directory context. // -// RPC method: session.auth.getStatus. +// RPC method: sessions.list. // -// Returns: Authentication status and account metadata for the session. -func (a *AuthApi) GetStatus(ctx context.Context) (*SessionAuthStatus, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.auth.getStatus", req) +// Parameters: Optional metadata-load limit and context filter applied to the returned +// sessions. +// +// Returns: Persisted sessions matching the filter, ordered most-recently-modified first. +func (a *ServerSessionsApi) List(ctx context.Context, params *SessionsListRequest) (*SessionList, error) { + raw, err := a.client.Request("sessions.list", params) if err != nil { return nil, err } - var result SessionAuthStatus + var result SessionList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type CommandsApi sessionApi - -// HandlePendingCommand reports completion of a pending client-handled slash command. +// LoadDeferredRepoHooks loads previously-deferred repo-level hooks on the active session, +// returning queued startup prompts. // -// RPC method: session.commands.handlePendingCommand. +// RPC method: sessions.loadDeferredRepoHooks. // -// Parameters: Pending command request ID and an optional error if the client handler failed. +// Parameters: Active session ID whose deferred repo-level hooks should be loaded. // -// Returns: Indicates whether the pending client-handled command was completed successfully. -func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *CommandsHandlePendingCommandRequest) (*CommandsHandlePendingCommandResult, error) { - req := map[string]any{"sessionId": a.sessionID} - if params != nil { - if params.Error != nil { - req["error"] = *params.Error - } - req["requestId"] = params.RequestID - } - raw, err := a.client.Request("session.commands.handlePendingCommand", req) +// Returns: Queued repo-level startup prompts and the total hook command count after loading. +func (a *ServerSessionsApi) LoadDeferredRepoHooks(ctx context.Context, params *SessionsLoadDeferredRepoHooksRequest) (*SessionLoadDeferredRepoHooksResult, error) { + raw, err := a.client.Request("sessions.loadDeferredRepoHooks", params) if err != nil { return nil, err } - var result CommandsHandlePendingCommandResult + var result SessionLoadDeferredRepoHooksResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Invokes a slash command in the session. +// PruneOld deletes sessions older than the given threshold, with optional dry-run and +// exclusion list. // -// RPC method: session.commands.invoke. +// RPC method: sessions.pruneOld. // -// Parameters: Slash command name and optional raw input string to invoke. +// Parameters: Age threshold and optional flags controlling which old sessions are pruned +// (or simulated when dryRun is true). // -// Returns: Result of invoking the slash command (text output, prompt to send to the agent, -// or completion). -func (a *CommandsApi) Invoke(ctx context.Context, params *CommandsInvokeRequest) (SlashCommandInvocationResult, error) { - req := map[string]any{"sessionId": a.sessionID} - if params != nil { - if params.Input != nil { - req["input"] = *params.Input - } - req["name"] = params.Name - } - raw, err := a.client.Request("session.commands.invoke", req) +// Returns: Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, +// total bytes freed, and the dry-run flag. +func (a *ServerSessionsApi) PruneOld(ctx context.Context, params *SessionsPruneOldRequest) (*SessionPruneResult, error) { + raw, err := a.client.Request("sessions.pruneOld", params) if err != nil { return nil, err } - result, err := unmarshalSlashCommandInvocationResult(raw) - if err != nil { + var result SessionPruneResult + if err := json.Unmarshal(raw, &result); err != nil { return nil, err } - return result, nil + return &result, nil } -// Lists slash commands available in the session. +// ReleaseLock releases the in-use lock held by this process for a session. // -// RPC method: session.commands.list. +// RPC method: sessions.releaseLock. // -// Parameters: Optional filters controlling which command sources to include in the listing. +// Parameters: Session ID whose in-use lock should be released. // -// Returns: Slash commands available in the session, after applying any include/exclude -// filters. -func (a *CommandsApi) List(ctx context.Context, params ...*CommandsListRequest) (*CommandList, error) { - var requestParams *CommandsListRequest - if len(params) > 0 { - requestParams = params[0] - } - req := map[string]any{"sessionId": a.sessionID} - if requestParams != nil { - if requestParams.IncludeBuiltins != nil { - req["includeBuiltins"] = *requestParams.IncludeBuiltins - } - if requestParams.IncludeClientCommands != nil { - req["includeClientCommands"] = *requestParams.IncludeClientCommands - } - if requestParams.IncludeSkills != nil { - req["includeSkills"] = *requestParams.IncludeSkills - } - } - raw, err := a.client.Request("session.commands.list", req) +// Returns: Release the in-use lock held by this process for the given session. No-op when +// this process does not currently hold a lock for the session. +func (a *ServerSessionsApi) ReleaseLock(ctx context.Context, params *SessionsReleaseLockRequest) (*SessionsReleaseLockResult, error) { + raw, err := a.client.Request("sessions.releaseLock", params) if err != nil { return nil, err } - var result CommandList + var result SessionsReleaseLockResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// RespondToQueuedCommand responds to a queued command request from the session. +// ReloadPluginHooks reloads user, plugin, and (optionally) repo hooks on the active session. // -// RPC method: session.commands.respondToQueuedCommand. +// RPC method: sessions.reloadPluginHooks. // -// Parameters: Queued command request ID and the result indicating whether the client -// handled it. +// Parameters: Active session ID and an optional flag for deferring repo-level hooks until +// folder trust. // -// Returns: Indicates whether the queued-command response was accepted by the session. -func (a *CommandsApi) RespondToQueuedCommand(ctx context.Context, params *CommandsRespondToQueuedCommandRequest) (*CommandsRespondToQueuedCommandResult, error) { - req := map[string]any{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - req["result"] = params.Result - } - raw, err := a.client.Request("session.commands.respondToQueuedCommand", req) +// Returns: Reload all hooks (user, plugin, optionally repo) and apply them to the active +// session. Call after installing or removing plugins so their hooks take effect +// immediately. No-op when no active session matches the given sessionId. +func (a *ServerSessionsApi) ReloadPluginHooks(ctx context.Context, params *SessionsReloadPluginHooksRequest) (*SessionsReloadPluginHooksResult, error) { + raw, err := a.client.Request("sessions.reloadPluginHooks", params) if err != nil { return nil, err } - var result CommandsRespondToQueuedCommandResult + var result SessionsReloadPluginHooksResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: ExtensionsApi contains experimental APIs that may change or be removed. -type ExtensionsApi sessionApi - -// Disables an extension for the session. +// Save flushes a session's pending events to disk. // -// RPC method: session.extensions.disable. +// RPC method: sessions.save. // -// Parameters: Source-qualified extension identifier to disable for the session. -func (a *ExtensionsApi) Disable(ctx context.Context, params *ExtensionsDisableRequest) (*SessionExtensionsDisableResult, error) { - req := map[string]any{"sessionId": a.sessionID} - if params != nil { - req["id"] = params.ID - } - raw, err := a.client.Request("session.extensions.disable", req) +// Parameters: Session ID whose pending events should be flushed to disk. +// +// Returns: Flush a session's pending events to disk. No-op when no writer exists for the +// session (e.g., already closed). +func (a *ServerSessionsApi) Save(ctx context.Context, params *SessionsSaveRequest) (*SessionsSaveResult, error) { + raw, err := a.client.Request("sessions.save", params) if err != nil { return nil, err } - var result SessionExtensionsDisableResult + var result SessionsSaveResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Enables an extension for the session. +// SetAdditionalPlugins replaces the manager-wide additional plugins registered with the +// session manager. // -// RPC method: session.extensions.enable. +// RPC method: sessions.setAdditionalPlugins. // -// Parameters: Source-qualified extension identifier to enable for the session. -func (a *ExtensionsApi) Enable(ctx context.Context, params *ExtensionsEnableRequest) (*SessionExtensionsEnableResult, error) { - req := map[string]any{"sessionId": a.sessionID} - if params != nil { - req["id"] = params.ID - } - raw, err := a.client.Request("session.extensions.enable", req) +// Parameters: Manager-wide additional plugins to register; replaces any +// previously-configured set. +// +// Returns: Replace the manager-wide additional plugins. New session creations and +// subsequent hook reloads see the new set; already-running sessions keep their existing +// hook installation until the next reload. +func (a *ServerSessionsApi) SetAdditionalPlugins(ctx context.Context, params *SessionsSetAdditionalPluginsRequest) (*SessionsSetAdditionalPluginsResult, error) { + raw, err := a.client.Request("sessions.setAdditionalPlugins", params) if err != nil { return nil, err } - var result SessionExtensionsEnableResult + var result SessionsSetAdditionalPluginsResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Lists extensions discovered for the session and their current status. +type ServerSkillsApi serverApi + +// Discovers skills across global and project sources. // -// RPC method: session.extensions.list. +// RPC method: skills.discover. // -// Returns: Extensions discovered for the session, with their current status. -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) +// Parameters: Optional project paths and additional skill directories to include in +// discovery. +// +// Returns: Skills discovered across global and project sources. +func (a *ServerSkillsApi) Discover(ctx context.Context, params *SkillsDiscoverRequest) (*ServerSkillList, error) { + raw, err := a.client.Request("skills.discover", params) if err != nil { return nil, err } - var result ExtensionList + var result ServerSkillList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Reloads extension definitions and processes for the session. +type ServerSkillsConfigApi serverApi + +// SetDisabledSkills replaces the global list of disabled skills. // -// RPC method: session.extensions.reload. -func (a *ExtensionsApi) Reload(ctx context.Context) (*SessionExtensionsReloadResult, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.extensions.reload", req) +// RPC method: skills.config.setDisabledSkills. +// +// Parameters: Skill names to mark as disabled in global configuration, replacing any +// previous list. +func (a *ServerSkillsConfigApi) SetDisabledSkills(ctx context.Context, params *SkillsConfigSetDisabledSkillsRequest) (*SkillsConfigSetDisabledSkillsResult, error) { + raw, err := a.client.Request("skills.config.setDisabledSkills", params) if err != nil { return nil, err } - var result SessionExtensionsReloadResult + var result SkillsConfigSetDisabledSkillsResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: FleetApi contains experimental APIs that may change or be removed. -type FleetApi sessionApi +func (s *ServerSkillsApi) Config() *ServerSkillsConfigApi { + return (*ServerSkillsConfigApi)(s) +} -// Starts fleet mode by submitting the fleet orchestration prompt to the session. +type ServerToolsApi serverApi + +// Lists built-in tools available for a model. // -// RPC method: session.fleet.start. +// RPC method: tools.list. // -// Parameters: Optional user prompt to combine with the fleet orchestration instructions. +// Parameters: Optional model identifier whose tool overrides should be applied to the +// listing. // -// Returns: Indicates whether fleet mode was successfully activated. -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 { - req["prompt"] = *params.Prompt - } - } - raw, err := a.client.Request("session.fleet.start", req) +// Returns: Built-in tools available for the requested model, with their parameters and +// instructions. +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 FleetStartResult + var result ToolList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: HistoryApi contains experimental APIs that may change or be removed. -type HistoryApi sessionApi +// ServerRpc provides typed server-scoped RPC methods. +type ServerRpc struct { + // Reuse a single struct instead of allocating one for each service on the heap. + common serverApi -// Compacts the session history to reduce context usage. + Account *ServerAccountApi + Mcp *ServerMcpApi + Models *ServerModelsApi + SessionFs *ServerSessionFsApi + Sessions *ServerSessionsApi + Skills *ServerSkillsApi + Tools *ServerToolsApi +} + +// Ping checks server responsiveness and returns protocol information. // -// RPC method: session.history.compact. +// RPC method: ping. // -// Returns: Compaction outcome with the number of tokens and messages removed and the -// resulting context window breakdown. -func (a *HistoryApi) Compact(ctx context.Context) (*HistoryCompactResult, error) { - req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.history.compact", req) +// Parameters: Optional message to echo back to the caller. +// +// Returns: Server liveness response, including the echoed message, current server +// timestamp, and protocol version. +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 } - var result HistoryCompactResult + var result PingResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Truncates persisted session history to a specific event. -// -// RPC method: session.history.truncate. -// -// Parameters: Identifier of the event to truncate to; this event and all later events are -// removed. -// +func NewServerRpc(client *jsonrpc2.Client) *ServerRpc { + r := &ServerRpc{} + r.common = serverApi{client: client} + r.Account = (*ServerAccountApi)(&r.common) + r.Mcp = (*ServerMcpApi)(&r.common) + r.Models = (*ServerModelsApi)(&r.common) + r.SessionFs = (*ServerSessionFsApi)(&r.common) + r.Sessions = (*ServerSessionsApi)(&r.common) + r.Skills = (*ServerSkillsApi)(&r.common) + r.Tools = (*ServerToolsApi)(&r.common) + return r +} + +type internalServerApi struct { + client *jsonrpc2.Client +} + +// InternalServerRpc provides internal SDK server-scoped RPC methods (handshake helpers +// etc.). Not part of the public API. +type InternalServerRpc struct { + // Reuse a single struct instead of allocating one for each service on the heap. + common internalServerApi +} + +// Connect performs the SDK server connection handshake and validates the optional +// connection token. +// +// RPC method: connect. +// +// Parameters: Optional connection token presented by the SDK client during the handshake. +// +// Returns: Handshake result reporting the server's protocol version and package version on +// success. +// Internal: Connect is part of the SDK's internal handshake/plumbing; external callers +// should not use it. +func (a *InternalServerRpc) Connect(ctx context.Context, params *ConnectRequest) (*ConnectResult, error) { + raw, err := a.common.client.Request("connect", params) + if err != nil { + return nil, err + } + var result ConnectResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +func NewInternalServerRpc(client *jsonrpc2.Client) *InternalServerRpc { + r := &InternalServerRpc{} + r.common = internalServerApi{client: client} + return r +} + +type sessionApi struct { + client *jsonrpc2.Client + sessionID string +} + +// Experimental: AgentApi contains experimental APIs that may change or be removed. +type AgentApi sessionApi + +// Deselect clears the selected custom agent and returns the session to the default agent. +// +// RPC method: session.agent.deselect. +func (a *AgentApi) Deselect(ctx context.Context) (*SessionAgentDeselectResult, 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 + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// GetCurrent gets the currently selected custom agent for the session. +// +// RPC method: session.agent.getCurrent. +// +// Returns: The currently selected custom agent, or null when using the default agent. +func (a *AgentApi) GetCurrent(ctx context.Context) (*AgentGetCurrentResult, 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 AgentGetCurrentResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Lists custom agents available to the session. +// +// RPC method: session.agent.list. +// +// Returns: Custom agents available to the session. +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 AgentList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Reloads custom agent definitions and returns the refreshed list. +// +// RPC method: session.agent.reload. +// +// Returns: Custom agents available to the session after reloading definitions from disk. +func (a *AgentApi) Reload(ctx context.Context) (*AgentReloadResult, 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 AgentReloadResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Selects a custom agent for subsequent turns in the session. +// +// RPC method: session.agent.select. +// +// Parameters: Name of the custom agent to select for subsequent turns. +// +// Returns: The newly selected custom agent. +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 + } + raw, err := a.client.Request("session.agent.select", req) + if err != nil { + return nil, err + } + var result AgentSelectResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +type AuthApi sessionApi + +// GetStatus gets authentication status and account metadata for the session. +// +// RPC method: session.auth.getStatus. +// +// Returns: Authentication status and account metadata for the session. +func (a *AuthApi) GetStatus(ctx context.Context) (*SessionAuthStatus, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.auth.getStatus", req) + if err != nil { + return nil, err + } + var result SessionAuthStatus + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// SetCredentials updates the session's auth credentials used for outbound model and API +// requests. +// +// RPC method: session.auth.setCredentials. +// +// Parameters: New auth credentials to install on the session. Omit to leave credentials +// unchanged. +// +// Returns: Indicates whether the credential update succeeded. +func (a *AuthApi) SetCredentials(ctx context.Context, params *SessionSetCredentialsParams) (*SessionSetCredentialsResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.Credentials != nil { + req["credentials"] = params.Credentials + } + } + raw, err := a.client.Request("session.auth.setCredentials", req) + if err != nil { + return nil, err + } + var result SessionSetCredentialsResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +type CommandsApi sessionApi + +// Enqueues a slash command for FIFO processing on the local session. +// +// RPC method: session.commands.enqueue. +// +// Parameters: Slash-prefixed command string to enqueue for FIFO processing. +// +// Returns: Indicates whether the command was accepted into the local execution queue. +func (a *CommandsApi) Enqueue(ctx context.Context, params *EnqueueCommandParams) (*EnqueueCommandResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["command"] = params.Command + } + raw, err := a.client.Request("session.commands.enqueue", req) + if err != nil { + return nil, err + } + var result EnqueueCommandResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Executes a slash command synchronously and returns any error. +// +// RPC method: session.commands.execute. +// +// Parameters: Slash command name and argument string to execute synchronously. +// +// Returns: Error message produced while executing the command, if any. +func (a *CommandsApi) Execute(ctx context.Context, params *ExecuteCommandParams) (*ExecuteCommandResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["args"] = params.Args + req["commandName"] = params.CommandName + } + raw, err := a.client.Request("session.commands.execute", req) + if err != nil { + return nil, err + } + var result ExecuteCommandResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// HandlePendingCommand reports completion of a pending client-handled slash command. +// +// RPC method: session.commands.handlePendingCommand. +// +// Parameters: Pending command request ID and an optional error if the client handler failed. +// +// Returns: Indicates whether the pending client-handled command was completed successfully. +func (a *CommandsApi) HandlePendingCommand(ctx context.Context, params *CommandsHandlePendingCommandRequest) (*CommandsHandlePendingCommandResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.Error != nil { + req["error"] = *params.Error + } + req["requestId"] = params.RequestID + } + raw, err := a.client.Request("session.commands.handlePendingCommand", req) + if err != nil { + return nil, err + } + var result CommandsHandlePendingCommandResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Invokes a slash command in the session. +// +// RPC method: session.commands.invoke. +// +// Parameters: Slash command name and optional raw input string to invoke. +// +// Returns: Result of invoking the slash command (text output, prompt to send to the agent, +// or completion). +func (a *CommandsApi) Invoke(ctx context.Context, params *CommandsInvokeRequest) (SlashCommandInvocationResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.Input != nil { + req["input"] = *params.Input + } + req["name"] = params.Name + } + raw, err := a.client.Request("session.commands.invoke", req) + if err != nil { + return nil, err + } + result, err := unmarshalSlashCommandInvocationResult(raw) + if err != nil { + return nil, err + } + return result, nil +} + +// Lists slash commands available in the session. +// +// RPC method: session.commands.list. +// +// Parameters: Optional filters controlling which command sources to include in the listing. +// +// Returns: Slash commands available in the session, after applying any include/exclude +// filters. +func (a *CommandsApi) List(ctx context.Context, params ...*CommandsListRequest) (*CommandList, error) { + var requestParams *CommandsListRequest + if len(params) > 0 { + requestParams = params[0] + } + req := map[string]any{"sessionId": a.sessionID} + if requestParams != nil { + if requestParams.IncludeBuiltins != nil { + req["includeBuiltins"] = *requestParams.IncludeBuiltins + } + if requestParams.IncludeClientCommands != nil { + req["includeClientCommands"] = *requestParams.IncludeClientCommands + } + if requestParams.IncludeSkills != nil { + req["includeSkills"] = *requestParams.IncludeSkills + } + } + raw, err := a.client.Request("session.commands.list", req) + if err != nil { + return nil, err + } + var result CommandList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RespondToQueuedCommand reports whether the host actually executed a queued command and +// whether to continue processing. +// +// RPC method: session.commands.respondToQueuedCommand. +// +// Parameters: Queued-command request ID and the result indicating whether the host executed +// it (and whether to stop processing further queued commands). +// +// Returns: Indicates whether the queued-command response was matched to a pending request. +func (a *CommandsApi) RespondToQueuedCommand(ctx context.Context, params *CommandsRespondToQueuedCommandRequest) (*CommandsRespondToQueuedCommandResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["result"] = params.Result + } + raw, err := a.client.Request("session.commands.respondToQueuedCommand", req) + if err != nil { + return nil, err + } + var result CommandsRespondToQueuedCommandResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: EventLogApi contains experimental APIs that may change or be removed. +type EventLogApi sessionApi + +// Reads a batch of session events from a cursor, optionally waiting for new events. +// +// RPC method: session.eventLog.read. +// +// Parameters: Cursor, batch size, and optional long-poll/filter parameters for reading +// session events. +// +// Returns: Batch of session events returned by a read, with cursor and continuation +// metadata. +func (a *EventLogApi) Read(ctx context.Context, params *EventLogReadRequest) (*EventsReadResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.AgentScope != nil { + req["agentScope"] = *params.AgentScope + } + if params.Cursor != nil { + req["cursor"] = *params.Cursor + } + if params.Max != nil { + req["max"] = *params.Max + } + if params.Types != nil { + req["types"] = *params.Types + } + if params.WaitMs != nil { + req["waitMs"] = *params.WaitMs + } + } + raw, err := a.client.Request("session.eventLog.read", req) + if err != nil { + return nil, err + } + var result EventsReadResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RegisterInterest registers consumer interest in an event type for runtime gating purposes. +// +// RPC method: session.eventLog.registerInterest. +// +// Parameters: Event type to register consumer interest for, used by runtime gating logic. +// +// Returns: Opaque handle representing an event-type interest registration. +func (a *EventLogApi) RegisterInterest(ctx context.Context, params *RegisterEventInterestParams) (*RegisterEventInterestResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["eventType"] = params.EventType + } + raw, err := a.client.Request("session.eventLog.registerInterest", req) + if err != nil { + return nil, err + } + var result RegisterEventInterestResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// ReleaseInterest releases a consumer's previously-registered interest in an event type. +// +// RPC method: session.eventLog.releaseInterest. +// +// Parameters: Opaque handle previously returned by `registerInterest` to release. +// +// Returns: Indicates whether the operation succeeded. +func (a *EventLogApi) ReleaseInterest(ctx context.Context, params *ReleaseEventInterestParams) (*EventLogReleaseInterestResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["handle"] = params.Handle + } + raw, err := a.client.Request("session.eventLog.releaseInterest", req) + if err != nil { + return nil, err + } + var result EventLogReleaseInterestResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Tail returns a snapshot of the current tail cursor without consuming events. +// +// RPC method: session.eventLog.tail. +// +// Returns: Snapshot of the current tail cursor without returning any events. Use this when +// a consumer wants to subscribe to live events going forward without first paginating +// through the entire persisted history (which would happen if `read` were called without a +// cursor on a long-lived session). +func (a *EventLogApi) Tail(ctx context.Context) (*EventLogTailResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.eventLog.tail", req) + if err != nil { + return nil, err + } + var result EventLogTailResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: ExtensionsApi contains experimental APIs that may change or be removed. +type ExtensionsApi sessionApi + +// Disables an extension for the session. +// +// RPC method: session.extensions.disable. +// +// Parameters: Source-qualified extension identifier to disable for the session. +func (a *ExtensionsApi) Disable(ctx context.Context, params *ExtensionsDisableRequest) (*SessionExtensionsDisableResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["id"] = params.ID + } + raw, err := a.client.Request("session.extensions.disable", req) + if err != nil { + return nil, err + } + var result SessionExtensionsDisableResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Enables an extension for the session. +// +// RPC method: session.extensions.enable. +// +// Parameters: Source-qualified extension identifier to enable for the session. +func (a *ExtensionsApi) Enable(ctx context.Context, params *ExtensionsEnableRequest) (*SessionExtensionsEnableResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["id"] = params.ID + } + raw, err := a.client.Request("session.extensions.enable", req) + if err != nil { + return nil, err + } + var result SessionExtensionsEnableResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Lists extensions discovered for the session and their current status. +// +// RPC method: session.extensions.list. +// +// Returns: Extensions discovered for the session, with their current status. +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 ExtensionList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Reloads extension definitions and processes for the session. +// +// RPC method: session.extensions.reload. +func (a *ExtensionsApi) Reload(ctx context.Context) (*SessionExtensionsReloadResult, 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 + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: FleetApi contains experimental APIs that may change or be removed. +type FleetApi sessionApi + +// Starts fleet mode by submitting the fleet orchestration prompt to the session. +// +// RPC method: session.fleet.start. +// +// Parameters: Optional user prompt to combine with the fleet orchestration instructions. +// +// Returns: Indicates whether fleet mode was successfully activated. +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 { + req["prompt"] = *params.Prompt + } + } + raw, err := a.client.Request("session.fleet.start", req) + if err != nil { + return nil, err + } + var result FleetStartResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: HistoryApi contains experimental APIs that may change or be removed. +type HistoryApi sessionApi + +// AbortManualCompaction aborts any in-progress manual compaction on a local session. +// +// RPC method: session.history.abortManualCompaction. +// +// Returns: Indicates whether an in-progress manual compaction was aborted. +func (a *HistoryApi) AbortManualCompaction(ctx context.Context) (*HistoryAbortManualCompactionResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.history.abortManualCompaction", req) + if err != nil { + return nil, err + } + var result HistoryAbortManualCompactionResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// CancelBackgroundCompaction cancels any in-progress background compaction on a local +// session. +// +// RPC method: session.history.cancelBackgroundCompaction. +// +// Returns: Indicates whether an in-progress background compaction was cancelled. +func (a *HistoryApi) CancelBackgroundCompaction(ctx context.Context) (*HistoryCancelBackgroundCompactionResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.history.cancelBackgroundCompaction", req) + if err != nil { + return nil, err + } + var result HistoryCancelBackgroundCompactionResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Compacts the session history to reduce context usage. +// +// RPC method: session.history.compact. +// +// Returns: Compaction outcome with the number of tokens and messages removed, summary text, +// and the resulting context window breakdown. +func (a *HistoryApi) Compact(ctx context.Context) (*HistoryCompactResult, 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 HistoryCompactResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// SummarizeForHandoff produces a markdown summary of the session's conversation context for +// hand-off scenarios. +// +// RPC method: session.history.summarizeForHandoff. +// +// Returns: Markdown summary of the conversation context (empty when not available). +func (a *HistoryApi) SummarizeForHandoff(ctx context.Context) (*HistorySummarizeForHandoffResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.history.summarizeForHandoff", req) + if err != nil { + return nil, err + } + var result HistorySummarizeForHandoffResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Truncates persisted session history to a specific event. +// +// RPC method: session.history.truncate. +// +// Parameters: Identifier of the event to truncate to; this event and all later events are +// removed. +// // Returns: Number of events that were removed by the truncation. 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 + req["eventId"] = params.EventID + } + raw, err := a.client.Request("session.history.truncate", req) + if err != nil { + return nil, err + } + var result HistoryTruncateResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +type InstructionsApi sessionApi + +// GetSources gets instruction sources loaded for the session. +// +// RPC method: session.instructions.getSources. +// +// Returns: Instruction sources loaded for the session, in merge order. +func (a *InstructionsApi) GetSources(ctx context.Context) (*InstructionsGetSourcesResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.instructions.getSources", req) + if err != nil { + return nil, err + } + var result InstructionsGetSourcesResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: LspApi contains experimental APIs that may change or be removed. +type LspApi sessionApi + +// Initialize loads the merged LSP configuration set for the session's working directory. +// +// RPC method: session.lsp.initialize. +// +// Parameters: Parameters for (re)loading the merged LSP configuration set. +func (a *LspApi) Initialize(ctx context.Context, params *LspInitializeRequest) (*SessionLspInitializeResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.Force != nil { + req["force"] = *params.Force + } + if params.GitRoot != nil { + req["gitRoot"] = *params.GitRoot + } + if params.WorkingDirectory != nil { + req["workingDirectory"] = *params.WorkingDirectory + } + } + raw, err := a.client.Request("session.lsp.initialize", req) + if err != nil { + return nil, err + } + var result SessionLspInitializeResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: McpApi contains experimental APIs that may change or be removed. +type McpApi sessionApi + +// CancelSamplingExecution cancels an in-flight MCP sampling execution by request ID. +// +// RPC method: session.mcp.cancelSamplingExecution. +// +// Parameters: The requestId previously passed to executeSampling that should be cancelled. +// +// Returns: Indicates whether an in-flight sampling execution with the given requestId was +// found and cancelled. +func (a *McpApi) CancelSamplingExecution(ctx context.Context, params *McpCancelSamplingExecutionParams) (*McpCancelSamplingExecutionResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + } + raw, err := a.client.Request("session.mcp.cancelSamplingExecution", req) + if err != nil { + return nil, err + } + var result McpCancelSamplingExecutionResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Disables an MCP server for the session. +// +// RPC method: session.mcp.disable. +// +// Parameters: Name of the MCP server to disable for the session. +func (a *McpApi) Disable(ctx context.Context, params *McpDisableRequest) (*SessionMcpDisableResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["serverName"] = params.ServerName + } + raw, err := a.client.Request("session.mcp.disable", req) + if err != nil { + return nil, err + } + var result SessionMcpDisableResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Enables an MCP server for the session. +// +// RPC method: session.mcp.enable. +// +// Parameters: Name of the MCP server to enable for the session. +func (a *McpApi) Enable(ctx context.Context, params *McpEnableRequest) (*SessionMcpEnableResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["serverName"] = params.ServerName + } + raw, err := a.client.Request("session.mcp.enable", req) + if err != nil { + return nil, err + } + var result SessionMcpEnableResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// ExecuteSampling runs an MCP sampling inference on behalf of an MCP server. +// +// RPC method: session.mcp.executeSampling. +// +// Parameters: Identifiers and raw MCP CreateMessageRequest params used to run a sampling +// inference. +// +// Returns: Outcome of an MCP sampling execution: success result, failure error, or +// cancellation. +func (a *McpApi) ExecuteSampling(ctx context.Context, params *McpExecuteSamplingParams) (*McpSamplingExecutionResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["mcpRequestId"] = params.McpRequestID + req["request"] = params.Request + req["requestId"] = params.RequestID + req["serverName"] = params.ServerName + } + raw, err := a.client.Request("session.mcp.executeSampling", req) + if err != nil { + return nil, err + } + var result McpSamplingExecutionResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Lists MCP servers configured for the session and their connection status. +// +// RPC method: session.mcp.list. +// +// Returns: MCP servers configured for the session, with their connection status. +func (a *McpApi) List(ctx context.Context) (*McpServerList, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.mcp.list", req) + if err != nil { + return nil, err + } + var result McpServerList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Reloads MCP server connections for the session. +// +// RPC method: session.mcp.reload. +func (a *McpApi) Reload(ctx context.Context) (*SessionMcpReloadResult, 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 + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RemoveGitHub removes the auto-managed `github` MCP server when present. +// +// RPC method: session.mcp.removeGitHub. +// +// Returns: Indicates whether the auto-managed `github` MCP server was removed (false when +// nothing to remove). +func (a *McpApi) RemoveGitHub(ctx context.Context) (*McpRemoveGitHubResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.mcp.removeGitHub", req) + if err != nil { + return nil, err + } + var result McpRemoveGitHubResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// SetEnvValueMode sets how environment-variable values supplied to MCP servers are resolved +// (direct or indirect). +// +// RPC method: session.mcp.setEnvValueMode. +// +// Parameters: Mode controlling how MCP server env values are resolved (`direct` or +// `indirect`). +// +// Returns: Env-value mode recorded on the session after the update. +func (a *McpApi) SetEnvValueMode(ctx context.Context, params *McpSetEnvValueModeParams) (*McpSetEnvValueModeResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["mode"] = params.Mode + } + raw, err := a.client.Request("session.mcp.setEnvValueMode", req) + if err != nil { + return nil, err + } + var result McpSetEnvValueModeResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: McpOauthApi contains experimental APIs that may change or be removed. +type McpOauthApi sessionApi + +// Login starts OAuth authentication for a remote MCP server. +// +// RPC method: session.mcp.oauth.login. +// +// Parameters: Remote MCP server name and optional overrides controlling reauthentication, +// OAuth client display name, and the callback success-page copy. +// +// Returns: OAuth authorization URL the caller should open, or empty when cached tokens +// already authenticated the server. +func (a *McpOauthApi) Login(ctx context.Context, params *McpOauthLoginRequest) (*McpOauthLoginResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + if params.CallbackSuccessMessage != nil { + req["callbackSuccessMessage"] = *params.CallbackSuccessMessage + } + if params.ClientName != nil { + req["clientName"] = *params.ClientName + } + if params.ForceReauth != nil { + req["forceReauth"] = *params.ForceReauth + } + req["serverName"] = params.ServerName + } + raw, err := a.client.Request("session.mcp.oauth.login", req) + if err != nil { + return nil, err + } + var result McpOauthLoginResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: Oauth returns experimental APIs that may change or be removed. +func (s *McpApi) Oauth() *McpOauthApi { + return (*McpOauthApi)(s) +} + +// Experimental: MetadataApi contains experimental APIs that may change or be removed. +type MetadataApi sessionApi + +// ContextInfo returns the token breakdown for the session's current context window for a +// given model. +// +// RPC method: session.metadata.contextInfo. +// +// Parameters: Model identifier and token limits used to compute the context-info breakdown. +// +// Returns: Token breakdown for the session's current context window, or null if +// uninitialized. +func (a *MetadataApi) ContextInfo(ctx context.Context, params *MetadataContextInfoRequest) (*MetadataContextInfoResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["outputTokenLimit"] = params.OutputTokenLimit + req["promptTokenLimit"] = params.PromptTokenLimit + if params.SelectedModel != nil { + req["selectedModel"] = *params.SelectedModel + } + } + raw, err := a.client.Request("session.metadata.contextInfo", req) + if err != nil { + return nil, err + } + var result MetadataContextInfoResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// IsProcessing reports whether the local session is currently processing user/agent +// messages. +// +// RPC method: session.metadata.isProcessing. +// +// Returns: Indicates whether the local session is currently processing a turn or background +// continuation. +func (a *MetadataApi) IsProcessing(ctx context.Context) (*MetadataIsProcessingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.metadata.isProcessing", req) + if err != nil { + return nil, err + } + var result MetadataIsProcessingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RecomputeContextTokens re-tokenizes the session's existing messages against a model and +// returns aggregate token totals. +// +// RPC method: session.metadata.recomputeContextTokens. +// +// Parameters: Model identifier to use when re-tokenizing the session's existing messages. +// +// Returns: Re-tokenize the session's existing messages against `modelId` and return the +// token totals. Useful for hosts that want an initial estimate of context usage on session +// resume, before the next agent turn fires `session.context_info_changed` events. Returns +// zeros for an empty session. +func (a *MetadataApi) RecomputeContextTokens(ctx context.Context, params *MetadataRecomputeContextTokensRequest) (*MetadataRecomputeContextTokensResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["modelId"] = params.ModelID + } + raw, err := a.client.Request("session.metadata.recomputeContextTokens", req) + if err != nil { + return nil, err + } + var result MetadataRecomputeContextTokensResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RecordContextChange records a working-directory/git context change and emits a +// `session.context_changed` event. +// +// RPC method: session.metadata.recordContextChange. +// +// Parameters: Updated working-directory/git context to record on the session. +// +// Returns: Notify the session that its working directory context has changed. Emits a +// `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline +// UI) can react. Use this when the host has detected a cwd/branch/repo change outside the +// session's normal lifecycle (e.g., after a shell command in interactive mode). +func (a *MetadataApi) RecordContextChange(ctx context.Context, params *MetadataRecordContextChangeRequest) (*MetadataRecordContextChangeResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["context"] = params.Context + } + raw, err := a.client.Request("session.metadata.recordContextChange", req) + if err != nil { + return nil, err + } + var result MetadataRecordContextChangeResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// SetWorkingDirectory updates the session's recorded working directory. +// +// RPC method: session.metadata.setWorkingDirectory. +// +// Parameters: Absolute path to set as the session's new working directory. +// +// Returns: Update the session's working directory. Used by the host when the user +// explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for +// `process.chdir` and any related side-effects (file index, etc.); this method only updates +// the session's own recorded path. +func (a *MetadataApi) SetWorkingDirectory(ctx context.Context, params *MetadataSetWorkingDirectoryRequest) (*MetadataSetWorkingDirectoryResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["workingDirectory"] = params.WorkingDirectory + } + raw, err := a.client.Request("session.metadata.setWorkingDirectory", req) + if err != nil { + return nil, err + } + var result MetadataSetWorkingDirectoryResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Snapshot returns a snapshot of the session's identifying metadata, mode, agent, and +// remote info. +// +// RPC method: session.metadata.snapshot. +// +// Returns: Point-in-time snapshot of slow-changing session identifier and state fields +func (a *MetadataApi) Snapshot(ctx context.Context) (*SessionMetadataSnapshot, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.metadata.snapshot", req) + if err != nil { + return nil, err + } + var result SessionMetadataSnapshot + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +type ModeApi sessionApi + +// Gets the current agent interaction mode. +// +// RPC method: session.mode.get. +// +// Returns: The session mode the agent is operating in +func (a *ModeApi) Get(ctx context.Context) (*SessionMode, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.mode.get", req) + if err != nil { + return nil, err + } + var result SessionMode + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Sets the current agent interaction mode. +// +// RPC method: session.mode.set. +// +// Parameters: Agent interaction mode to apply to the session. +func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionModeSetResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["mode"] = params.Mode + } + raw, err := a.client.Request("session.mode.set", req) + if err != nil { + return nil, err + } + var result SessionModeSetResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +type ModelApi sessionApi + +// GetCurrent gets the currently selected model for the session. +// +// RPC method: session.model.getCurrent. +// +// Returns: The currently selected model and reasoning effort for the session. +func (a *ModelApi) GetCurrent(ctx context.Context) (*CurrentModel, 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 CurrentModel + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// SetReasoningEffort updates the session's reasoning effort without changing the selected +// model. +// +// RPC method: session.model.setReasoningEffort. +// +// Parameters: Reasoning effort level to apply to the currently selected model. +// +// Returns: Update the session's reasoning effort without changing the selected model. Use +// `switchTo` instead when you also need to change the model. The runtime stores the effort +// on the session and applies it to subsequent turns. +func (a *ModelApi) SetReasoningEffort(ctx context.Context, params *ModelSetReasoningEffortRequest) (*ModelSetReasoningEffortResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["reasoningEffort"] = params.ReasoningEffort } - raw, err := a.client.Request("session.history.truncate", req) + raw, err := a.client.Request("session.model.setReasoningEffort", req) if err != nil { return nil, err } - var result HistoryTruncateResult + var result ModelSetReasoningEffortResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type InstructionsApi sessionApi - -// GetSources gets instruction sources loaded for the session. +// SwitchTo switches the session to a model and optional reasoning configuration. // -// RPC method: session.instructions.getSources. +// RPC method: session.model.switchTo. // -// Returns: Instruction sources loaded for the session, in merge order. -func (a *InstructionsApi) GetSources(ctx context.Context) (*InstructionsGetSourcesResult, error) { +// Parameters: Target model identifier and optional reasoning effort, summary, and +// capability overrides. +// +// Returns: The model identifier active on the session after the switch. +func (a *ModelApi) SwitchTo(ctx context.Context, params *ModelSwitchToRequest) (*ModelSwitchToResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.instructions.getSources", req) + if params != nil { + if params.ModelCapabilities != nil { + req["modelCapabilities"] = *params.ModelCapabilities + } + req["modelId"] = params.ModelID + if params.ReasoningEffort != nil { + req["reasoningEffort"] = *params.ReasoningEffort + } + if params.ReasoningSummary != nil { + req["reasoningSummary"] = *params.ReasoningSummary + } + } + raw, err := a.client.Request("session.model.switchTo", req) if err != nil { return nil, err } - var result InstructionsGetSourcesResult + var result ModelSwitchToResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: McpApi contains experimental APIs that may change or be removed. -type McpApi sessionApi +type NameApi sessionApi -// Disables an MCP server for the session. +// Gets the session's friendly name. // -// RPC method: session.mcp.disable. +// RPC method: session.name.get. // -// Parameters: Name of the MCP server to disable for the session. -func (a *McpApi) Disable(ctx context.Context, params *McpDisableRequest) (*SessionMcpDisableResult, error) { +// Returns: The session's friendly name, or null when not yet set. +func (a *NameApi) Get(ctx context.Context) (*NameGetResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.name.get", req) + if err != nil { + return nil, err + } + var result NameGetResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Sets the session's friendly name. +// +// RPC method: session.name.set. +// +// Parameters: New friendly name to apply to the session. +func (a *NameApi) Set(ctx context.Context, params *NameSetRequest) (*SessionNameSetResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - req["serverName"] = params.ServerName + req["name"] = params.Name } - raw, err := a.client.Request("session.mcp.disable", req) + raw, err := a.client.Request("session.name.set", req) if err != nil { return nil, err } - var result SessionMcpDisableResult + var result SessionNameSetResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Enables an MCP server for the session. +// SetAuto persists an auto-generated session summary as the session's name when no user-set +// name exists. // -// RPC method: session.mcp.enable. +// RPC method: session.name.setAuto. // -// Parameters: Name of the MCP server to enable for the session. -func (a *McpApi) Enable(ctx context.Context, params *McpEnableRequest) (*SessionMcpEnableResult, error) { +// Parameters: Auto-generated session summary to apply as the session's name when no +// user-set name exists. +// +// Returns: Indicates whether the auto-generated summary was applied as the session's name. +func (a *NameApi) SetAuto(ctx context.Context, params *NameSetAutoRequest) (*NameSetAutoResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - req["serverName"] = params.ServerName + req["summary"] = params.Summary } - raw, err := a.client.Request("session.mcp.enable", req) + raw, err := a.client.Request("session.name.setAuto", req) if err != nil { return nil, err } - var result SessionMcpEnableResult + var result NameSetAutoResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Lists MCP servers configured for the session and their connection status. +// Experimental: OptionsApi contains experimental APIs that may change or be removed. +type OptionsApi sessionApi + +// Update patches the genuinely-mutable subset of session options. // -// RPC method: session.mcp.list. +// RPC method: session.options.update. // -// Returns: MCP servers configured for the session, with their connection status. -func (a *McpApi) List(ctx context.Context) (*McpServerList, error) { +// Parameters: Patch of mutable session options to apply to the running session. +// +// Returns: Indicates whether the session options patch was applied successfully. +func (a *OptionsApi) Update(ctx context.Context, params *SessionUpdateOptionsParams) (*SessionUpdateOptionsResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.mcp.list", req) + if params != nil { + if params.AdditionalContentExclusionPolicies != nil { + req["additionalContentExclusionPolicies"] = params.AdditionalContentExclusionPolicies + } + if params.AgentContext != nil { + req["agentContext"] = *params.AgentContext + } + if params.AskUserDisabled != nil { + req["askUserDisabled"] = *params.AskUserDisabled + } + if params.AvailableTools != nil { + req["availableTools"] = params.AvailableTools + } + if params.ClientName != nil { + req["clientName"] = *params.ClientName + } + if params.CoauthorEnabled != nil { + req["coauthorEnabled"] = *params.CoauthorEnabled + } + if params.ContinueOnAutoMode != nil { + req["continueOnAutoMode"] = *params.ContinueOnAutoMode + } + if params.CopilotURL != nil { + req["copilotUrl"] = *params.CopilotURL + } + if params.CustomAgentsLocalOnly != nil { + req["customAgentsLocalOnly"] = *params.CustomAgentsLocalOnly + } + if params.DisabledInstructionSources != nil { + req["disabledInstructionSources"] = params.DisabledInstructionSources + } + if params.DisabledSkills != nil { + req["disabledSkills"] = params.DisabledSkills + } + if params.EnableOnDemandInstructionDiscovery != nil { + req["enableOnDemandInstructionDiscovery"] = *params.EnableOnDemandInstructionDiscovery + } + if params.EnableReasoningSummaries != nil { + req["enableReasoningSummaries"] = *params.EnableReasoningSummaries + } + if params.EnableScriptSafety != nil { + req["enableScriptSafety"] = *params.EnableScriptSafety + } + if params.EnableStreaming != nil { + req["enableStreaming"] = *params.EnableStreaming + } + if params.EnvValueMode != nil { + req["envValueMode"] = *params.EnvValueMode + } + if params.EventsLogDirectory != nil { + req["eventsLogDirectory"] = *params.EventsLogDirectory + } + if params.ExcludedTools != nil { + req["excludedTools"] = params.ExcludedTools + } + if params.FeatureFlags != nil { + req["featureFlags"] = params.FeatureFlags + } + if params.InstalledPlugins != nil { + req["installedPlugins"] = params.InstalledPlugins + } + if params.IntegrationID != nil { + req["integrationId"] = *params.IntegrationID + } + if params.IsExperimentalMode != nil { + req["isExperimentalMode"] = *params.IsExperimentalMode + } + if params.LogInteractiveShells != nil { + req["logInteractiveShells"] = *params.LogInteractiveShells + } + if params.LspClientName != nil { + req["lspClientName"] = *params.LspClientName + } + if params.ManageScheduleEnabled != nil { + req["manageScheduleEnabled"] = *params.ManageScheduleEnabled + } + if params.Model != nil { + req["model"] = *params.Model + } + if params.Provider != nil { + req["provider"] = params.Provider + } + if params.ReasoningEffort != nil { + req["reasoningEffort"] = *params.ReasoningEffort + } + if params.RunningInInteractiveMode != nil { + req["runningInInteractiveMode"] = *params.RunningInInteractiveMode + } + if params.SandboxConfig != nil { + req["sandboxConfig"] = params.SandboxConfig + } + if params.ShellInitProfile != nil { + req["shellInitProfile"] = *params.ShellInitProfile + } + if params.ShellProcessFlags != nil { + req["shellProcessFlags"] = params.ShellProcessFlags + } + if params.SkillDirectories != nil { + req["skillDirectories"] = params.SkillDirectories + } + if params.SkipCustomInstructions != nil { + req["skipCustomInstructions"] = *params.SkipCustomInstructions + } + if params.TrajectoryFile != nil { + req["trajectoryFile"] = *params.TrajectoryFile + } + if params.WorkingDirectory != nil { + req["workingDirectory"] = *params.WorkingDirectory + } + } + raw, err := a.client.Request("session.options.update", req) if err != nil { return nil, err } - var result McpServerList + var result SessionUpdateOptionsResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Reloads MCP server connections for the session. +type PermissionsApi sessionApi + +// Configure replaces selected permission policy fields (rules, paths, URLs, exclusions, +// allow-all flags) on the session. // -// RPC method: session.mcp.reload. -func (a *McpApi) Reload(ctx context.Context) (*SessionMcpReloadResult, error) { +// RPC method: session.permissions.configure. +// +// Parameters: Patch of permission policy fields to apply (omit a field to leave it +// unchanged). +// +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) Configure(ctx context.Context, params *PermissionsConfigureParams) (*PermissionsConfigureResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.mcp.reload", req) + if params != nil { + if params.AdditionalContentExclusionPolicies != nil { + req["additionalContentExclusionPolicies"] = params.AdditionalContentExclusionPolicies + } + if params.ApproveAllReadPermissionRequests != nil { + req["approveAllReadPermissionRequests"] = *params.ApproveAllReadPermissionRequests + } + if params.ApproveAllToolPermissionRequests != nil { + req["approveAllToolPermissionRequests"] = *params.ApproveAllToolPermissionRequests + } + if params.Paths != nil { + req["paths"] = *params.Paths + } + if params.Rules != nil { + req["rules"] = *params.Rules + } + if params.Urls != nil { + req["urls"] = *params.Urls + } + } + raw, err := a.client.Request("session.permissions.configure", req) if err != nil { return nil, err } - var result SessionMcpReloadResult + var result PermissionsConfigureResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: McpOauthApi contains experimental APIs that may change or be removed. -type McpOauthApi sessionApi +// HandlePendingPermissionRequest provides a decision for a pending tool permission request. +// +// RPC method: session.permissions.handlePendingPermissionRequest. +// +// Parameters: Pending permission request ID and the decision to apply (approve/reject and +// scope). +// +// Returns: Indicates whether the permission decision was applied; false when the request +// was already resolved. +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 + req["result"] = params.Result + } + raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) + if err != nil { + return nil, err + } + var result PermissionRequestResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} -// Login starts OAuth authentication for a remote MCP server. +// ModifyRules adds or removes session-scoped or location-scoped permission rules. // -// RPC method: session.mcp.oauth.login. +// RPC method: session.permissions.modifyRules. // -// Parameters: Remote MCP server name and optional overrides controlling reauthentication, -// OAuth client display name, and the callback success-page copy. +// Parameters: Scope and add/remove instructions for modifying session- or location-scoped +// permission rules. // -// Returns: OAuth authorization URL the caller should open, or empty when cached tokens -// already authenticated the server. -func (a *McpOauthApi) Login(ctx context.Context, params *McpOauthLoginRequest) (*McpOauthLoginResult, error) { +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) ModifyRules(ctx context.Context, params *PermissionsModifyRulesParams) (*PermissionsModifyRulesResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - if params.CallbackSuccessMessage != nil { - req["callbackSuccessMessage"] = *params.CallbackSuccessMessage + if params.Add != nil { + req["add"] = params.Add } - if params.ClientName != nil { - req["clientName"] = *params.ClientName + if params.Remove != nil { + req["remove"] = params.Remove } - if params.ForceReauth != nil { - req["forceReauth"] = *params.ForceReauth + if params.RemoveAll != nil { + req["removeAll"] = *params.RemoveAll } - req["serverName"] = params.ServerName + req["scope"] = params.Scope } - raw, err := a.client.Request("session.mcp.oauth.login", req) + raw, err := a.client.Request("session.permissions.modifyRules", req) if err != nil { return nil, err } - var result McpOauthLoginResult + var result PermissionsModifyRulesResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Experimental: Oauth returns experimental APIs that may change or be removed. -func (s *McpApi) Oauth() *McpOauthApi { - return (*McpOauthApi)(s) +// NotifyPromptShown notifies the runtime that a permission prompt UI has been shown to the +// user. +// +// RPC method: session.permissions.notifyPromptShown. +// +// Parameters: Notification payload describing the permission prompt that the client just +// rendered. +// +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) NotifyPromptShown(ctx context.Context, params *PermissionPromptShownNotification) (*PermissionsNotifyPromptShownResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["message"] = params.Message + } + raw, err := a.client.Request("session.permissions.notifyPromptShown", req) + if err != nil { + return nil, err + } + var result PermissionsNotifyPromptShownResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil } -type ModeApi sessionApi +// PendingRequests reconstructs the set of pending tool permission requests from the +// session's event history. +// +// RPC method: session.permissions.pendingRequests. +// +// Returns: List of pending permission requests reconstructed from event history. +func (a *PermissionsApi) PendingRequests(ctx context.Context) (*PendingPermissionRequestList, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.permissions.pendingRequests", req) + if err != nil { + return nil, err + } + var result PendingPermissionRequestList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} -// Gets the current agent interaction mode. +// ResetSessionApprovals clears session-scoped tool permission approvals. // -// RPC method: session.mode.get. +// RPC method: session.permissions.resetSessionApprovals. // -// Returns: The session mode the agent is operating in -func (a *ModeApi) Get(ctx context.Context) (*SessionMode, error) { +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) ResetSessionApprovals(ctx context.Context) (*PermissionsResetSessionApprovalsResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.mode.get", req) + raw, err := a.client.Request("session.permissions.resetSessionApprovals", req) if err != nil { return nil, err } - var result SessionMode + var result PermissionsResetSessionApprovalsResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Sets the current agent interaction mode. +// SetApproveAll enables or disables automatic approval of tool permission requests for the +// session. // -// RPC method: session.mode.set. +// RPC method: session.permissions.setApproveAll. // -// Parameters: Agent interaction mode to apply to the session. -func (a *ModeApi) Set(ctx context.Context, params *ModeSetRequest) (*SessionModeSetResult, error) { +// Parameters: Allow-all toggle for tool permission requests, with an optional telemetry +// source. +// +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) SetApproveAll(ctx context.Context, params *PermissionsSetApproveAllRequest) (*PermissionsSetApproveAllResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - req["mode"] = params.Mode + req["enabled"] = params.Enabled + if params.Source != nil { + req["source"] = *params.Source + } } - raw, err := a.client.Request("session.mode.set", req) + raw, err := a.client.Request("session.permissions.setApproveAll", req) if err != nil { return nil, err } - var result SessionModeSetResult + var result PermissionsSetApproveAllResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type ModelApi sessionApi - -// GetCurrent gets the currently selected model for the session. +// SetRequired sets whether the client wants permission prompts bridged into session events. // -// RPC method: session.model.getCurrent. +// RPC method: session.permissions.setRequired. // -// Returns: The currently selected model for the session. -func (a *ModelApi) GetCurrent(ctx context.Context) (*CurrentModel, error) { +// Parameters: Toggles whether permission prompts should be bridged into session events for +// this client. +// +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsApi) SetRequired(ctx context.Context, params *PermissionsSetRequiredRequest) (*PermissionsSetRequiredResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.model.getCurrent", req) + if params != nil { + req["required"] = params.Required + } + raw, err := a.client.Request("session.permissions.setRequired", req) if err != nil { return nil, err } - var result CurrentModel + var result PermissionsSetRequiredResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// SwitchTo switches the session to a model and optional reasoning configuration. +type PermissionsPathsApi sessionApi + +// Adds a directory to the session's allow-list. // -// RPC method: session.model.switchTo. +// RPC method: session.permissions.paths.add. // -// Parameters: Target model identifier and optional reasoning effort, summary, and -// capability overrides. +// Parameters: Directory path to add to the session's allowed directories. // -// Returns: The model identifier active on the session after the switch. -func (a *ModelApi) SwitchTo(ctx context.Context, params *ModelSwitchToRequest) (*ModelSwitchToResult, error) { +// Returns: Indicates whether the operation succeeded. +func (a *PermissionsPathsApi) Add(ctx context.Context, params *PermissionPathsAddParams) (*PermissionsPathsAddResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - if params.ModelCapabilities != nil { - req["modelCapabilities"] = *params.ModelCapabilities - } - req["modelId"] = params.ModelID - if params.ReasoningEffort != nil { - req["reasoningEffort"] = *params.ReasoningEffort - } - if params.ReasoningSummary != nil { - req["reasoningSummary"] = *params.ReasoningSummary - } + req["path"] = params.Path } - raw, err := a.client.Request("session.model.switchTo", req) + raw, err := a.client.Request("session.permissions.paths.add", req) if err != nil { return nil, err } - var result ModelSwitchToResult + var result PermissionsPathsAddResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type NameApi sessionApi - -// Gets the session's friendly name. +// IsPathWithinAllowedDirectories reports whether a path falls within any of the session's +// allowed directories. // -// RPC method: session.name.get. +// RPC method: session.permissions.paths.isPathWithinAllowedDirectories. // -// Returns: The session's friendly name, or null when not yet set. -func (a *NameApi) Get(ctx context.Context) (*NameGetResult, error) { +// Parameters: Path to evaluate against the session's allowed directories. +// +// Returns: Indicates whether the supplied path is within the session's allowed directories. +func (a *PermissionsPathsApi) IsPathWithinAllowedDirectories(ctx context.Context, params *PermissionPathsAllowedCheckParams) (*PermissionPathsAllowedCheckResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.name.get", req) + if params != nil { + req["path"] = params.Path + } + raw, err := a.client.Request("session.permissions.paths.isPathWithinAllowedDirectories", req) if err != nil { return nil, err } - var result NameGetResult + var result PermissionPathsAllowedCheckResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// Sets the session's friendly name. +// IsPathWithinWorkspace reports whether a path falls within the session's workspace +// (primary) directory. // -// RPC method: session.name.set. +// RPC method: session.permissions.paths.isPathWithinWorkspace. // -// Parameters: New friendly name to apply to the session. -func (a *NameApi) Set(ctx context.Context, params *NameSetRequest) (*SessionNameSetResult, error) { +// Parameters: Path to evaluate against the session's workspace (primary) directory. +// +// Returns: Indicates whether the supplied path is within the session's workspace directory. +func (a *PermissionsPathsApi) IsPathWithinWorkspace(ctx context.Context, params *PermissionPathsWorkspaceCheckParams) (*PermissionPathsWorkspaceCheckResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { - req["name"] = params.Name + req["path"] = params.Path } - raw, err := a.client.Request("session.name.set", req) + raw, err := a.client.Request("session.permissions.paths.isPathWithinWorkspace", req) if err != nil { return nil, err } - var result SessionNameSetResult + var result PermissionPathsWorkspaceCheckResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -type PermissionsApi sessionApi - -// HandlePendingPermissionRequest provides a decision for a pending tool permission request. -// -// RPC method: session.permissions.handlePendingPermissionRequest. +// List returns the session's allowed directories and primary working directory. // -// Parameters: Pending permission request ID and the decision to apply (approve/reject and -// scope). +// RPC method: session.permissions.paths.list. // -// Returns: Indicates whether the permission decision was applied; false when the request -// was already resolved. -func (a *PermissionsApi) HandlePendingPermissionRequest(ctx context.Context, params *PermissionDecisionRequest) (*PermissionRequestResult, error) { +// Returns: Snapshot of the session's allow-listed directories and primary working directory. +func (a *PermissionsPathsApi) List(ctx context.Context) (*PermissionPathsList, error) { req := map[string]any{"sessionId": a.sessionID} - if params != nil { - req["requestId"] = params.RequestID - req["result"] = params.Result - } - raw, err := a.client.Request("session.permissions.handlePendingPermissionRequest", req) + raw, err := a.client.Request("session.permissions.paths.list", req) if err != nil { return nil, err } - var result PermissionRequestResult + var result PermissionPathsList if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// ResetSessionApprovals clears session-scoped tool permission approvals. +// UpdatePrimary updates the session's primary working directory used by the permission +// policy. // -// RPC method: session.permissions.resetSessionApprovals. +// RPC method: session.permissions.paths.updatePrimary. +// +// Parameters: Directory path to set as the session's new primary working directory. // // Returns: Indicates whether the operation succeeded. -func (a *PermissionsApi) ResetSessionApprovals(ctx context.Context) (*PermissionsResetSessionApprovalsResult, error) { +func (a *PermissionsPathsApi) UpdatePrimary(ctx context.Context, params *PermissionPathsUpdatePrimaryParams) (*PermissionsPathsUpdatePrimaryResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.permissions.resetSessionApprovals", req) + if params != nil { + req["path"] = params.Path + } + raw, err := a.client.Request("session.permissions.paths.updatePrimary", req) if err != nil { return nil, err } - var result PermissionsResetSessionApprovalsResult + var result PermissionsPathsUpdatePrimaryResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } -// SetApproveAll enables or disables automatic approval of tool permission requests for the -// session. +func (s *PermissionsApi) Paths() *PermissionsPathsApi { + return (*PermissionsPathsApi)(s) +} + +type PermissionsUrlsApi sessionApi + +// SetUnrestrictedMode toggles the runtime's URL-permission policy between unrestricted and +// restricted modes. // -// RPC method: session.permissions.setApproveAll. +// RPC method: session.permissions.urls.setUnrestrictedMode. // -// Parameters: Whether to auto-approve all tool permission requests for the rest of the -// session. +// Parameters: Whether the URL-permission policy should run in unrestricted mode. // // Returns: Indicates whether the operation succeeded. -func (a *PermissionsApi) SetApproveAll(ctx context.Context, params *PermissionsSetApproveAllRequest) (*PermissionsSetApproveAllResult, error) { +func (a *PermissionsUrlsApi) SetUnrestrictedMode(ctx context.Context, params *PermissionUrlsSetUnrestrictedModeParams) (*PermissionsUrlsSetUnrestrictedModeResult, error) { req := map[string]any{"sessionId": a.sessionID} if params != nil { req["enabled"] = params.Enabled } - raw, err := a.client.Request("session.permissions.setApproveAll", req) + raw, err := a.client.Request("session.permissions.urls.setUnrestrictedMode", req) if err != nil { return nil, err } - var result PermissionsSetApproveAllResult + var result PermissionsUrlsSetUnrestrictedModeResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } return &result, nil } +func (s *PermissionsApi) Urls() *PermissionsUrlsApi { + return (*PermissionsUrlsApi)(s) +} + type PlanApi sessionApi // Deletes the session plan file from the workspace. @@ -4317,6 +8494,62 @@ func (a *PluginsApi) List(ctx context.Context) (*PluginList, error) { return &result, nil } +// Experimental: QueueApi contains experimental APIs that may change or be removed. +type QueueApi sessionApi + +// Clears all pending queued items on the local session. +// +// RPC method: session.queue.clear. +func (a *QueueApi) Clear(ctx context.Context) (*SessionQueueClearResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.queue.clear", req) + if err != nil { + return nil, err + } + var result SessionQueueClearResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// PendingItems returns the local session's pending user-facing queued items and steering +// messages. +// +// RPC method: session.queue.pendingItems. +// +// Returns: Snapshot of the session's pending queued items and immediate-steering messages. +func (a *QueueApi) PendingItems(ctx context.Context) (*QueuePendingItemsResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.queue.pendingItems", req) + if err != nil { + return nil, err + } + var result QueuePendingItemsResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RemoveMostRecent removes the most recently queued user-facing item (LIFO). +// +// RPC method: session.queue.removeMostRecent. +// +// Returns: Indicates whether a user-facing pending item was removed. +func (a *QueueApi) RemoveMostRecent(ctx context.Context) (*QueueRemoveMostRecentResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.queue.removeMostRecent", req) + if err != nil { + return nil, err + } + var result QueueRemoveMostRecentResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Experimental: RemoteApi contains experimental APIs that may change or be removed. type RemoteApi sessionApi @@ -4363,6 +8596,78 @@ func (a *RemoteApi) Enable(ctx context.Context, params *RemoteEnableRequest) (*R return &result, nil } +// NotifySteerableChanged persists a remote-steerability change emitted by the host as a +// session event. +// +// RPC method: session.remote.notifySteerableChanged. +// +// Parameters: New remote-steerability state to persist as a +// `session.remote_steerable_changed` event. +// +// Returns: Persist a steerability change as a `session.remote_steerable_changed` event. +// Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling +// steering on a remote exporter that the runtime does not directly own. +func (a *RemoteApi) NotifySteerableChanged(ctx context.Context, params *RemoteNotifySteerableChangedRequest) (*RemoteNotifySteerableChangedResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["remoteSteerable"] = params.RemoteSteerable + } + raw, err := a.client.Request("session.remote.notifySteerableChanged", req) + if err != nil { + return nil, err + } + var result RemoteNotifySteerableChangedResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: ScheduleApi contains experimental APIs that may change or be removed. +type ScheduleApi sessionApi + +// Lists the session's currently active scheduled prompts. +// +// RPC method: session.schedule.list. +// +// Returns: Snapshot of the currently active recurring prompts for this session. +func (a *ScheduleApi) List(ctx context.Context) (*ScheduleList, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.schedule.list", req) + if err != nil { + return nil, err + } + var result ScheduleList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Stop removes a scheduled prompt by id. +// +// RPC method: session.schedule.stop. +// +// Parameters: Identifier of the scheduled prompt to remove. +// +// Returns: Remove a scheduled prompt by id. The result entry is omitted if the id was +// unknown. +func (a *ScheduleApi) Stop(ctx context.Context, params *ScheduleStopRequest) (*ScheduleStopResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["id"] = params.ID + } + raw, err := a.client.Request("session.schedule.stop", req) + if err != nil { + return nil, err + } + var result ScheduleStopResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + type ShellApi sessionApi // Exec starts a shell command and streams output through session notifications. @@ -4469,6 +8774,41 @@ func (a *SkillsApi) Enable(ctx context.Context, params *SkillsEnableRequest) (*S return &result, nil } +// EnsureLoaded ensures the session's skill definitions have been loaded from disk. +// +// RPC method: session.skills.ensureLoaded. +func (a *SkillsApi) EnsureLoaded(ctx context.Context) (*SessionSkillsEnsureLoadedResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.skills.ensureLoaded", req) + if err != nil { + return nil, err + } + var result SessionSkillsEnsureLoadedResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// GetInvoked returns the skills that have been invoked during this session. +// +// RPC method: session.skills.getInvoked. +// +// Returns: Skills invoked during this session, ordered by invocation time (most recent +// last). +func (a *SkillsApi) GetInvoked(ctx context.Context) (*SkillsGetInvokedResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.skills.getInvoked", req) + if err != nil { + return nil, err + } + var result SkillsGetInvokedResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Lists skills available to the session. // // RPC method: session.skills.list. @@ -4532,18 +8872,80 @@ func (a *TasksApi) Cancel(ctx context.Context, params *TasksCancelRequest) (*Tas return &result, nil } +// GetCurrentPromotable returns the first sync-waiting task that can currently be promoted +// to background mode. +// +// RPC method: session.tasks.getCurrentPromotable. +// +// Returns: The first sync-waiting task that can currently be promoted to background mode. +func (a *TasksApi) GetCurrentPromotable(ctx context.Context) (*TasksGetCurrentPromotableResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.tasks.getCurrentPromotable", req) + if err != nil { + return nil, err + } + var result TasksGetCurrentPromotableResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// GetProgress returns progress information for a background task by ID. +// +// RPC method: session.tasks.getProgress. +// +// Parameters: Identifier of the background task to fetch progress for. +// +// Returns: Progress information for the task, or null when no task with that ID is tracked. +func (a *TasksApi) GetProgress(ctx context.Context, params *TasksGetProgressRequest) (*TasksGetProgressResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["id"] = params.ID + } + raw, err := a.client.Request("session.tasks.getProgress", req) + if err != nil { + return nil, err + } + var result TasksGetProgressResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Lists background tasks tracked by the session. // // RPC method: session.tasks.list. // -// Returns: Background tasks currently tracked by the session. -func (a *TasksApi) List(ctx context.Context) (*TaskList, error) { +// Returns: Background tasks currently tracked by the session. +func (a *TasksApi) List(ctx context.Context) (*TaskList, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.tasks.list", req) + if err != nil { + return nil, err + } + var result TaskList + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// PromoteCurrentToBackground atomically promotes the first promotable sync-waiting task to +// background mode and returns it. +// +// RPC method: session.tasks.promoteCurrentToBackground. +// +// Returns: The promoted task as it now exists in background mode, omitted if no promotable +// task was waiting. +func (a *TasksApi) PromoteCurrentToBackground(ctx context.Context) (*TasksPromoteCurrentToBackgroundResult, error) { req := map[string]any{"sessionId": a.sessionID} - raw, err := a.client.Request("session.tasks.list", req) + raw, err := a.client.Request("session.tasks.promoteCurrentToBackground", req) if err != nil { return nil, err } - var result TaskList + var result TasksPromoteCurrentToBackgroundResult if err := json.Unmarshal(raw, &result); err != nil { return nil, err } @@ -4574,6 +8976,25 @@ func (a *TasksApi) PromoteToBackground(ctx context.Context, params *TasksPromote return &result, nil } +// Refreshes metadata for any detached background shells the runtime knows about. +// +// RPC method: session.tasks.refresh. +// +// Returns: Refresh metadata for any detached background shells the runtime knows about. Use +// after a long pause to pick up exit/output state for shells running outside the agent loop. +func (a *TasksApi) Refresh(ctx context.Context) (*TasksRefreshResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.tasks.refresh", req) + if err != nil { + return nil, err + } + var result TasksRefreshResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Removes a completed or cancelled background task from tracking. // // RPC method: session.tasks.remove. @@ -4659,6 +9080,53 @@ func (a *TasksApi) StartAgent(ctx context.Context, params *TasksStartAgentReques return &result, nil } +// WaitForPending waits for all in-flight background tasks and any follow-up turns to settle. +// +// RPC method: session.tasks.waitForPending. +// +// Returns: Wait until all in-flight background tasks (agents + shells) and any follow-up +// turns scheduled by their completions have settled. Returns when the runtime is fully +// drained or after an internal timeout (default 10 minutes; configurable via +// COPILOT_TASK_WAIT_TIMEOUT_SECONDS). +func (a *TasksApi) WaitForPending(ctx context.Context) (*TasksWaitForPendingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.tasks.waitForPending", req) + if err != nil { + return nil, err + } + var result TasksWaitForPendingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Experimental: TelemetryApi contains experimental APIs that may change or be removed. +type TelemetryApi sessionApi + +// SetFeatureOverrides sets feature override key/value pairs to attach to subsequent +// telemetry events for the session. +// +// RPC method: session.telemetry.setFeatureOverrides. +// +// Parameters: Feature override key/value pairs to attach to subsequent telemetry events +// from this session. +func (a *TelemetryApi) SetFeatureOverrides(ctx context.Context, params *TelemetrySetFeatureOverridesRequest) (*SessionTelemetrySetFeatureOverridesResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["features"] = params.Features + } + raw, err := a.client.Request("session.telemetry.setFeatureOverrides", req) + if err != nil { + return nil, err + } + var result SessionTelemetrySetFeatureOverridesResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + type ToolsApi sessionApi // HandlePendingToolCall provides the result for a pending external tool call. @@ -4691,6 +9159,28 @@ func (a *ToolsApi) HandlePendingToolCall(ctx context.Context, params *HandlePend return &result, nil } +// InitializeAndValidate resolves, builds, and validates the runtime tool list for the +// session. +// +// RPC method: session.tools.initializeAndValidate. +// +// Returns: Resolve, build, and validate the runtime tool list for this session. Subagent +// sessions and consumer flows that need an initialized tool set before `send` invoke this. +// Default base-class implementation is a no-op for sessions that don't support tool +// validation. +func (a *ToolsApi) InitializeAndValidate(ctx context.Context) (*ToolsInitializeAndValidateResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.tools.initializeAndValidate", req) + if err != nil { + return nil, err + } + var result ToolsInitializeAndValidateResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + type UIApi sessionApi // Elicitation requests structured input from a UI-capable client. @@ -4718,6 +9208,32 @@ func (a *UIApi) Elicitation(ctx context.Context, params *UIElicitationRequest) ( return &result, nil } +// HandlePendingAutoModeSwitch resolves a pending `auto_mode_switch.requested` event with +// the user's accept/decline decision. +// +// RPC method: session.ui.handlePendingAutoModeSwitch. +// +// Parameters: Request ID of a pending `auto_mode_switch.requested` event and the user's +// response. +// +// Returns: Indicates whether the pending UI request was resolved by this call. +func (a *UIApi) HandlePendingAutoModeSwitch(ctx context.Context, params *UIHandlePendingAutoModeSwitchRequest) (*UIHandlePendingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["response"] = params.Response + } + raw, err := a.client.Request("session.ui.handlePendingAutoModeSwitch", req) + if err != nil { + return nil, err + } + var result UIHandlePendingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // HandlePendingElicitation provides the user response for a pending elicitation request. // // RPC method: session.ui.handlePendingElicitation. @@ -4744,6 +9260,133 @@ func (a *UIApi) HandlePendingElicitation(ctx context.Context, params *UIHandlePe return &result, nil } +// HandlePendingExitPlanMode resolves a pending `exit_plan_mode.requested` event with the +// user's response. +// +// RPC method: session.ui.handlePendingExitPlanMode. +// +// Parameters: Request ID of a pending `exit_plan_mode.requested` event and the user's +// response. +// +// Returns: Indicates whether the pending UI request was resolved by this call. +func (a *UIApi) HandlePendingExitPlanMode(ctx context.Context, params *UIHandlePendingExitPlanModeRequest) (*UIHandlePendingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["response"] = params.Response + } + raw, err := a.client.Request("session.ui.handlePendingExitPlanMode", req) + if err != nil { + return nil, err + } + var result UIHandlePendingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// HandlePendingSampling resolves a pending `sampling.requested` event with a sampling +// result, or rejects it. +// +// RPC method: session.ui.handlePendingSampling. +// +// Parameters: Request ID of a pending `sampling.requested` event and an optional sampling +// result payload (omit to reject). +// +// Returns: Indicates whether the pending UI request was resolved by this call. +func (a *UIApi) HandlePendingSampling(ctx context.Context, params *UIHandlePendingSamplingRequest) (*UIHandlePendingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + if params.Response != nil { + req["response"] = *params.Response + } + } + raw, err := a.client.Request("session.ui.handlePendingSampling", req) + if err != nil { + return nil, err + } + var result UIHandlePendingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// HandlePendingUserInput resolves a pending `user_input.requested` event with the user's +// response. +// +// RPC method: session.ui.handlePendingUserInput. +// +// Parameters: Request ID of a pending `user_input.requested` event and the user's response. +// +// Returns: Indicates whether the pending UI request was resolved by this call. +func (a *UIApi) HandlePendingUserInput(ctx context.Context, params *UIHandlePendingUserInputRequest) (*UIHandlePendingResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["requestId"] = params.RequestID + req["response"] = params.Response + } + raw, err := a.client.Request("session.ui.handlePendingUserInput", req) + if err != nil { + return nil, err + } + var result UIHandlePendingResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// RegisterDirectAutoModeSwitchHandler registers an in-process handler for auto-mode-switch +// requests so the server bridge skips dispatch. +// +// RPC method: session.ui.registerDirectAutoModeSwitchHandler. +// +// Returns: Register an in-process handler for `auto_mode_switch.requested` events. The +// caller still attaches the actual listener via the standard event-subscription mechanism; +// this registration solely tells the server bridge to skip its own dispatch (so a remote +// client doesn't race the in-process handler for the same requestId). +func (a *UIApi) RegisterDirectAutoModeSwitchHandler(ctx context.Context) (*UIRegisterDirectAutoModeSwitchHandlerResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.ui.registerDirectAutoModeSwitchHandler", req) + if err != nil { + return nil, err + } + var result UIRegisterDirectAutoModeSwitchHandlerResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// UnregisterDirectAutoModeSwitchHandler unregisters a previously-registered in-process +// auto-mode-switch handler by its opaque handle. +// +// RPC method: session.ui.unregisterDirectAutoModeSwitchHandler. +// +// Parameters: Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to +// release. +// +// Returns: Indicates whether the handle was active and the registration count was +// decremented. +func (a *UIApi) UnregisterDirectAutoModeSwitchHandler(ctx context.Context, params *UIUnregisterDirectAutoModeSwitchHandlerRequest) (*UIUnregisterDirectAutoModeSwitchHandlerResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["handle"] = params.Handle + } + raw, err := a.client.Request("session.ui.unregisterDirectAutoModeSwitchHandler", req) + if err != nil { + return nil, err + } + var result UIUnregisterDirectAutoModeSwitchHandlerResult + 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 @@ -4794,7 +9437,8 @@ func (a *WorkspacesApi) CreateFile(ctx context.Context, params *WorkspacesCreate // // RPC method: session.workspaces.getWorkspace. // -// Returns: Current workspace metadata for the session, or null when not available. +// Returns: Current workspace metadata for the session, including its absolute filesystem +// path when available. func (a *WorkspacesApi) GetWorkspace(ctx context.Context) (*WorkspacesGetWorkspaceResult, error) { req := map[string]any{"sessionId": a.sessionID} raw, err := a.client.Request("session.workspaces.getWorkspace", req) @@ -4808,6 +9452,25 @@ func (a *WorkspacesApi) GetWorkspace(ctx context.Context) (*WorkspacesGetWorkspa return &result, nil } +// ListCheckpoints lists workspace checkpoints in chronological order. +// +// RPC method: session.workspaces.listCheckpoints. +// +// Returns: Workspace checkpoints in chronological order; empty when the workspace is not +// enabled. +func (a *WorkspacesApi) ListCheckpoints(ctx context.Context) (*WorkspacesListCheckpointsResult, error) { + req := map[string]any{"sessionId": a.sessionID} + raw, err := a.client.Request("session.workspaces.listCheckpoints", req) + if err != nil { + return nil, err + } + var result WorkspacesListCheckpointsResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // ListFiles lists files stored in the session workspace files directory. // // RPC method: session.workspaces.listFiles. @@ -4826,6 +9489,30 @@ func (a *WorkspacesApi) ListFiles(ctx context.Context) (*WorkspacesListFilesResu return &result, nil } +// ReadCheckpoint reads the content of a workspace checkpoint by number. +// +// RPC method: session.workspaces.readCheckpoint. +// +// Parameters: Checkpoint number to read. +// +// Returns: Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace +// is missing. +func (a *WorkspacesApi) ReadCheckpoint(ctx context.Context, params *WorkspacesReadCheckpointRequest) (*WorkspacesReadCheckpointResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["number"] = params.Number + } + raw, err := a.client.Request("session.workspaces.readCheckpoint", req) + if err != nil { + return nil, err + } + var result WorkspacesReadCheckpointResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // ReadFile reads a file from the session workspace files directory. // // RPC method: session.workspaces.readFile. @@ -4849,6 +9536,29 @@ func (a *WorkspacesApi) ReadFile(ctx context.Context, params *WorkspacesReadFile return &result, nil } +// SaveLargePaste saves pasted content as a UTF-8 file in the session workspace. +// +// RPC method: session.workspaces.saveLargePaste. +// +// Parameters: Pasted content to save as a UTF-8 file in the session workspace. +// +// Returns: Descriptor for the saved paste file, or null when the workspace is unavailable. +func (a *WorkspacesApi) SaveLargePaste(ctx context.Context, params *WorkspacesSaveLargePasteRequest) (*WorkspacesSaveLargePasteResult, error) { + req := map[string]any{"sessionId": a.sessionID} + if params != nil { + req["content"] = params.Content + } + raw, err := a.client.Request("session.workspaces.saveLargePaste", req) + if err != nil { + return nil, err + } + var result WorkspacesSaveLargePasteResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // SessionRpc provides typed session-scoped RPC methods. type SessionRpc struct { // Reuse a single struct instead of allocating one for each service on the heap. @@ -4857,33 +9567,65 @@ type SessionRpc struct { Agent *AgentApi Auth *AuthApi Commands *CommandsApi + EventLog *EventLogApi Extensions *ExtensionsApi Fleet *FleetApi History *HistoryApi Instructions *InstructionsApi + Lsp *LspApi Mcp *McpApi + Metadata *MetadataApi Mode *ModeApi Model *ModelApi Name *NameApi + Options *OptionsApi Permissions *PermissionsApi Plan *PlanApi Plugins *PluginsApi + Queue *QueueApi Remote *RemoteApi + Schedule *ScheduleApi Shell *ShellApi Skills *SkillsApi Tasks *TasksApi + Telemetry *TelemetryApi Tools *ToolsApi UI *UIApi Usage *UsageApi Workspaces *WorkspacesApi } +// Aborts the current agent turn. +// +// RPC method: session.abort. +// +// Parameters: Parameters for aborting the current turn +// +// Returns: Result of aborting the current turn +func (a *SessionRpc) Abort(ctx context.Context, params *AbortRequest) (*AbortResult, error) { + req := map[string]any{"sessionId": a.common.sessionID} + if params != nil { + if params.Reason != nil { + req["reason"] = *params.Reason + } + } + raw, err := a.common.client.Request("session.abort", req) + if err != nil { + return nil, err + } + var result AbortResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Log emits a user-visible session log event. // // RPC method: session.log. // -// Parameters: Message text, optional severity level, persistence flag, and optional -// follow-up URL. +// Parameters: Message text, optional severity level, persistence flag, optional follow-up +// URL, and optional tip. // // Returns: Identifier of the session event that was emitted for the log message. func (a *SessionRpc) Log(ctx context.Context, params *LogRequest) (*LogResult, error) { @@ -4896,6 +9638,12 @@ func (a *SessionRpc) Log(ctx context.Context, params *LogRequest) (*LogResult, e req["level"] = *params.Level } req["message"] = params.Message + if params.Tip != nil { + req["tip"] = *params.Tip + } + if params.Type != nil { + req["type"] = *params.Type + } if params.URL != nil { req["url"] = *params.URL } @@ -4911,6 +9659,93 @@ func (a *SessionRpc) Log(ctx context.Context, params *LogRequest) (*LogResult, e return &result, nil } +// Sends a user message to the session and returns its message ID. +// +// RPC method: session.send. +// +// Parameters: Parameters for sending a user message to the session +// +// Returns: Result of sending a user message +func (a *SessionRpc) Send(ctx context.Context, params *SendRequest) (*SendResult, error) { + req := map[string]any{"sessionId": a.common.sessionID} + if params != nil { + if params.AgentMode != nil { + req["agentMode"] = *params.AgentMode + } + if params.Attachments != nil { + req["attachments"] = params.Attachments + } + if params.Billable != nil { + req["billable"] = *params.Billable + } + if params.DisplayPrompt != nil { + req["displayPrompt"] = *params.DisplayPrompt + } + if params.Mode != nil { + req["mode"] = *params.Mode + } + if params.Prepend != nil { + req["prepend"] = *params.Prepend + } + req["prompt"] = params.Prompt + if params.RequestHeaders != nil { + req["requestHeaders"] = params.RequestHeaders + } + if params.RequiredTool != nil { + req["requiredTool"] = *params.RequiredTool + } + if params.Source != nil { + req["source"] = params.Source + } + if params.Traceparent != nil { + req["traceparent"] = *params.Traceparent + } + if params.Tracestate != nil { + req["tracestate"] = *params.Tracestate + } + if params.Wait != nil { + req["wait"] = *params.Wait + } + } + raw, err := a.common.client.Request("session.send", req) + if err != nil { + return nil, err + } + var result SendResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + +// Shutdown shuts down the session and persists its final state. Awaits any deferred +// sessionEnd hooks before resolving so user-supplied hook scripts complete before the +// runtime tears down. +// +// RPC method: session.shutdown. +// +// Parameters: Parameters for shutting down the session +func (a *SessionRpc) Shutdown(ctx context.Context, params *ShutdownRequest) (*SessionShutdownResult, error) { + req := map[string]any{"sessionId": a.common.sessionID} + if params != nil { + if params.Reason != nil { + req["reason"] = *params.Reason + } + if params.Type != nil { + req["type"] = *params.Type + } + } + raw, err := a.common.client.Request("session.shutdown", req) + if err != nil { + return nil, err + } + var result SessionShutdownResult + if err := json.Unmarshal(raw, &result); err != nil { + return nil, err + } + return &result, nil +} + // Suspends the session while preserving persisted state for later resume. // // RPC method: session.suspend. @@ -4933,21 +9768,28 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc { r.Agent = (*AgentApi)(&r.common) r.Auth = (*AuthApi)(&r.common) r.Commands = (*CommandsApi)(&r.common) + r.EventLog = (*EventLogApi)(&r.common) r.Extensions = (*ExtensionsApi)(&r.common) r.Fleet = (*FleetApi)(&r.common) r.History = (*HistoryApi)(&r.common) r.Instructions = (*InstructionsApi)(&r.common) + r.Lsp = (*LspApi)(&r.common) r.Mcp = (*McpApi)(&r.common) + r.Metadata = (*MetadataApi)(&r.common) r.Mode = (*ModeApi)(&r.common) r.Model = (*ModelApi)(&r.common) r.Name = (*NameApi)(&r.common) + r.Options = (*OptionsApi)(&r.common) r.Permissions = (*PermissionsApi)(&r.common) r.Plan = (*PlanApi)(&r.common) r.Plugins = (*PluginsApi)(&r.common) + r.Queue = (*QueueApi)(&r.common) r.Remote = (*RemoteApi)(&r.common) + r.Schedule = (*ScheduleApi)(&r.common) r.Shell = (*ShellApi)(&r.common) r.Skills = (*SkillsApi)(&r.common) r.Tasks = (*TasksApi)(&r.common) + r.Telemetry = (*TelemetryApi)(&r.common) r.Tools = (*ToolsApi)(&r.common) r.UI = (*UIApi)(&r.common) r.Usage = (*UsageApi)(&r.common) diff --git a/go/rpc/zrpc_encoding.go b/go/rpc/zrpc_encoding.go index 554b13893..617550389 100644 --- a/go/rpc/zrpc_encoding.go +++ b/go/rpc/zrpc_encoding.go @@ -8,6 +8,154 @@ import ( "errors" ) +func unmarshalAuthInfo(data []byte) (AuthInfo, error) { + if string(data) == "null" { + return nil, nil + } + type rawUnion struct { + Type AuthInfoType `json:"type"` + } + var raw rawUnion + if err := json.Unmarshal(data, &raw); err != nil { + return nil, err + } + + switch raw.Type { + case AuthInfoTypeAPIKey: + var d APIKeyAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeCopilotAPIToken: + var d CopilotAPITokenAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeEnv: + var d EnvAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeGhCli: + var d GhCliAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeHmac: + var d HMACAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeToken: + var d TokenAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case AuthInfoTypeUser: + var d UserAuthInfo + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + default: + return &RawAuthInfoData{Discriminator: raw.Type, Raw: data}, nil + } +} + +func (r RawAuthInfoData) MarshalJSON() ([]byte, error) { + if r.Raw != nil { + return r.Raw, nil + } + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + }{ + Type: r.Discriminator, + }) +} + +func (r APIKeyAuthInfo) MarshalJSON() ([]byte, error) { + type alias APIKeyAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r CopilotAPITokenAuthInfo) MarshalJSON() ([]byte, error) { + type alias CopilotAPITokenAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r EnvAuthInfo) MarshalJSON() ([]byte, error) { + type alias EnvAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r GhCliAuthInfo) MarshalJSON() ([]byte, error) { + type alias GhCliAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r HMACAuthInfo) MarshalJSON() ([]byte, error) { + type alias HMACAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r TokenAuthInfo) MarshalJSON() ([]byte, error) { + type alias TokenAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r UserAuthInfo) MarshalJSON() ([]byte, error) { + type alias UserAuthInfo + return json.Marshal(struct { + Type AuthInfoType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + func unmarshalQueuedCommandResult(data []byte) (QueuedCommandResult, error) { if string(data) == "null" { return nil, nil @@ -82,6 +230,38 @@ func (r *CommandsRespondToQueuedCommandRequest) UnmarshalJSON(data []byte) error return nil } +func (r EventLogTypes) MarshalJSON() ([]byte, error) { + if r.String != nil { + return json.Marshal(r.String) + } + if r.StringArray != nil { + return json.Marshal(r.StringArray) + } + return []byte("null"), nil +} + +func (r *EventLogTypes) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + *r = EventLogTypes{} + return nil + } + { + var value EventLogTypesString + if err := json.Unmarshal(data, &value); err == nil { + *r = EventLogTypes{String: &value} + return nil + } + } + { + var value []string + if err := json.Unmarshal(data, &value); err == nil { + *r = EventLogTypes{StringArray: value} + return nil + } + } + return errors.New("data did not match any union variant for EventLogTypes") +} + func unmarshalExternalToolTextResultForLlmContent(data []byte) (ExternalToolTextResultForLlmContent, error) { if string(data) == "null" { return nil, nil @@ -380,6 +560,58 @@ func (r *HandlePendingToolCallRequest) UnmarshalJSON(data []byte) error { return nil } +func (r InstalledPluginSource) MarshalJSON() ([]byte, error) { + if r.InstalledPluginSourceGithub != nil { + return json.Marshal(r.InstalledPluginSourceGithub) + } + if r.InstalledPluginSourceLocal != nil { + return json.Marshal(r.InstalledPluginSourceLocal) + } + if r.InstalledPluginSourceURL != nil { + return json.Marshal(r.InstalledPluginSourceURL) + } + if r.String != nil { + return json.Marshal(r.String) + } + return []byte("null"), nil +} + +func (r *InstalledPluginSource) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + *r = InstalledPluginSource{} + return nil + } + { + var value InstalledPluginSourceGithub + if err := json.Unmarshal(data, &value); err == nil { + *r = InstalledPluginSource{InstalledPluginSourceGithub: &value} + return nil + } + } + { + var value InstalledPluginSourceLocal + if err := json.Unmarshal(data, &value); err == nil { + *r = InstalledPluginSource{InstalledPluginSourceLocal: &value} + return nil + } + } + { + var value InstalledPluginSourceURL + if err := json.Unmarshal(data, &value); err == nil { + *r = InstalledPluginSource{InstalledPluginSourceURL: &value} + return nil + } + } + { + var value string + if err := json.Unmarshal(data, &value); err == nil { + *r = InstalledPluginSource{String: &value} + return nil + } + } + return errors.New("data did not match any union variant for InstalledPluginSource") +} + func matchesMcpServerConfigHTTP(data []byte) bool { var rawGroup0 struct { Command json.RawMessage `json:"command"` @@ -604,6 +836,60 @@ func unmarshalPermissionDecision(data []byte) (PermissionDecision, error) { return nil, err } return &d, nil + case PermissionDecisionKindApproved: + var d PermissionDecisionApproved + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindApprovedForLocation: + var d PermissionDecisionApprovedForLocation + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindApprovedForSession: + var d PermissionDecisionApprovedForSession + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindCancelled: + var d PermissionDecisionCancelled + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindDeniedByContentExclusionPolicy: + var d PermissionDecisionDeniedByContentExclusionPolicy + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindDeniedByPermissionRequestHook: + var d PermissionDecisionDeniedByPermissionRequestHook + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindDeniedByRules: + var d PermissionDecisionDeniedByRules + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindDeniedInteractivelyByUser: + var d PermissionDecisionDeniedInteractivelyByUser + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionKindDeniedNoApprovalRuleAndCouldNotRequestFromUser: + var d PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil case PermissionDecisionKindReject: var d PermissionDecisionReject if err := json.Unmarshal(data, &d); err != nil { @@ -632,12 +918,23 @@ func (r RawPermissionDecisionData) MarshalJSON() ([]byte, error) { }) } -func unmarshalPermissionDecisionApproveForLocationApproval(data []byte) (PermissionDecisionApproveForLocationApproval, error) { +func (r PermissionDecisionApproved) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproved + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func unmarshalUserToolSessionApproval(data []byte) (UserToolSessionApproval, error) { if string(data) == "null" { return nil, nil } type rawUnion struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` } var raw rawUnion if err := json.Unmarshal(data, &raw); err != nil { @@ -645,80 +942,74 @@ func unmarshalPermissionDecisionApproveForLocationApproval(data []byte) (Permiss } switch raw.Kind { - case PermissionDecisionApproveForLocationApprovalKindCommands: - var d PermissionDecisionApproveForLocationApprovalCommands - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case PermissionDecisionApproveForLocationApprovalKindCustomTool: - var d PermissionDecisionApproveForLocationApprovalCustomTool + case UserToolSessionApprovalKindCommands: + var d UserToolSessionApprovalCommands if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindExtensionManagement: - var d PermissionDecisionApproveForLocationApprovalExtensionManagement + case UserToolSessionApprovalKindCustomTool: + var d UserToolSessionApprovalCustomTool if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindExtensionPermissionAccess: - var d PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess + case UserToolSessionApprovalKindExtensionManagement: + var d UserToolSessionApprovalExtensionManagement if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindMcp: - var d PermissionDecisionApproveForLocationApprovalMcp + case UserToolSessionApprovalKindExtensionPermissionAccess: + var d UserToolSessionApprovalExtensionPermissionAccess if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindMcpSampling: - var d PermissionDecisionApproveForLocationApprovalMcpSampling + case UserToolSessionApprovalKindMcp: + var d UserToolSessionApprovalMcp if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindMemory: - var d PermissionDecisionApproveForLocationApprovalMemory + case UserToolSessionApprovalKindMemory: + var d UserToolSessionApprovalMemory if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindRead: - var d PermissionDecisionApproveForLocationApprovalRead + case UserToolSessionApprovalKindRead: + var d UserToolSessionApprovalRead if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil - case PermissionDecisionApproveForLocationApprovalKindWrite: - var d PermissionDecisionApproveForLocationApprovalWrite + case UserToolSessionApprovalKindWrite: + var d UserToolSessionApprovalWrite if err := json.Unmarshal(data, &d); err != nil { return nil, err } return &d, nil default: - return &RawPermissionDecisionApproveForLocationApprovalData{Discriminator: raw.Kind, Raw: data}, nil + return &RawUserToolSessionApprovalData{Discriminator: raw.Kind, Raw: data}, nil } } -func (r RawPermissionDecisionApproveForLocationApprovalData) MarshalJSON() ([]byte, error) { +func (r RawUserToolSessionApprovalData) MarshalJSON() ([]byte, error) { if r.Raw != nil { return r.Raw, nil } return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` }{ Kind: r.Discriminator, }) } -func (r PermissionDecisionApproveForLocationApprovalCommands) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalCommands +func (r UserToolSessionApprovalCommands) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalCommands return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -726,10 +1017,10 @@ func (r PermissionDecisionApproveForLocationApprovalCommands) MarshalJSON() ([]b }) } -func (r PermissionDecisionApproveForLocationApprovalCustomTool) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalCustomTool +func (r UserToolSessionApprovalCustomTool) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalCustomTool return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -737,10 +1028,10 @@ func (r PermissionDecisionApproveForLocationApprovalCustomTool) MarshalJSON() ([ }) } -func (r PermissionDecisionApproveForLocationApprovalExtensionManagement) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalExtensionManagement +func (r UserToolSessionApprovalExtensionManagement) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalExtensionManagement return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -748,10 +1039,10 @@ func (r PermissionDecisionApproveForLocationApprovalExtensionManagement) Marshal }) } -func (r PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess +func (r UserToolSessionApprovalExtensionPermissionAccess) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalExtensionPermissionAccess return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -759,10 +1050,10 @@ func (r PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess) M }) } -func (r PermissionDecisionApproveForLocationApprovalMcp) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalMcp +func (r UserToolSessionApprovalMcp) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalMcp return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -770,10 +1061,10 @@ func (r PermissionDecisionApproveForLocationApprovalMcp) MarshalJSON() ([]byte, }) } -func (r PermissionDecisionApproveForLocationApprovalMcpSampling) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalMcpSampling +func (r UserToolSessionApprovalMemory) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalMemory return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -781,10 +1072,10 @@ func (r PermissionDecisionApproveForLocationApprovalMcpSampling) MarshalJSON() ( }) } -func (r PermissionDecisionApproveForLocationApprovalMemory) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalMemory +func (r UserToolSessionApprovalRead) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalRead return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -792,10 +1083,10 @@ func (r PermissionDecisionApproveForLocationApprovalMemory) MarshalJSON() ([]byt }) } -func (r PermissionDecisionApproveForLocationApprovalRead) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalRead +func (r UserToolSessionApprovalWrite) MarshalJSON() ([]byte, error) { + type alias UserToolSessionApprovalWrite return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + Kind UserToolSessionApprovalKind `json:"kind"` alias }{ Kind: r.Kind(), @@ -803,12 +1094,243 @@ func (r PermissionDecisionApproveForLocationApprovalRead) MarshalJSON() ([]byte, }) } -func (r PermissionDecisionApproveForLocationApprovalWrite) MarshalJSON() ([]byte, error) { - type alias PermissionDecisionApproveForLocationApprovalWrite - return json.Marshal(struct { - Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` - alias - }{ +func (r *PermissionDecisionApprovedForLocation) UnmarshalJSON(data []byte) error { + type rawPermissionDecisionApprovedForLocation struct { + Approval json.RawMessage `json:"approval"` + LocationKey string `json:"locationKey"` + } + var raw rawPermissionDecisionApprovedForLocation + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + if raw.Approval != nil { + value, err := unmarshalUserToolSessionApproval(raw.Approval) + if err != nil { + return err + } + r.Approval = value + } + r.LocationKey = raw.LocationKey + return nil +} + +func (r PermissionDecisionApprovedForLocation) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApprovedForLocation + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r *PermissionDecisionApprovedForSession) UnmarshalJSON(data []byte) error { + type rawPermissionDecisionApprovedForSession struct { + Approval json.RawMessage `json:"approval"` + } + var raw rawPermissionDecisionApprovedForSession + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + if raw.Approval != nil { + value, err := unmarshalUserToolSessionApproval(raw.Approval) + if err != nil { + return err + } + r.Approval = value + } + return nil +} + +func (r PermissionDecisionApprovedForSession) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApprovedForSession + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func unmarshalPermissionDecisionApproveForLocationApproval(data []byte) (PermissionDecisionApproveForLocationApproval, error) { + if string(data) == "null" { + return nil, nil + } + type rawUnion struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + } + var raw rawUnion + if err := json.Unmarshal(data, &raw); err != nil { + return nil, err + } + + switch raw.Kind { + case PermissionDecisionApproveForLocationApprovalKindCommands: + var d PermissionDecisionApproveForLocationApprovalCommands + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindCustomTool: + var d PermissionDecisionApproveForLocationApprovalCustomTool + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindExtensionManagement: + var d PermissionDecisionApproveForLocationApprovalExtensionManagement + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindExtensionPermissionAccess: + var d PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindMcp: + var d PermissionDecisionApproveForLocationApprovalMcp + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindMcpSampling: + var d PermissionDecisionApproveForLocationApprovalMcpSampling + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindMemory: + var d PermissionDecisionApproveForLocationApprovalMemory + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindRead: + var d PermissionDecisionApproveForLocationApprovalRead + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case PermissionDecisionApproveForLocationApprovalKindWrite: + var d PermissionDecisionApproveForLocationApprovalWrite + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + default: + return &RawPermissionDecisionApproveForLocationApprovalData{Discriminator: raw.Kind, Raw: data}, nil + } +} + +func (r RawPermissionDecisionApproveForLocationApprovalData) MarshalJSON() ([]byte, error) { + if r.Raw != nil { + return r.Raw, nil + } + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + }{ + Kind: r.Discriminator, + }) +} + +func (r PermissionDecisionApproveForLocationApprovalCommands) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalCommands + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalCustomTool) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalCustomTool + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalExtensionManagement) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalExtensionManagement + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalMcp) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalMcp + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalMcpSampling) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalMcpSampling + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalMemory) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalMemory + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalRead) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalRead + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionApproveForLocationApprovalWrite) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionApproveForLocationApprovalWrite + return json.Marshal(struct { + Kind PermissionDecisionApproveForLocationApprovalKind `json:"kind"` + alias + }{ Kind: r.Kind(), alias: alias(r), }) @@ -1080,6 +1602,72 @@ func (r PermissionDecisionApprovePermanently) MarshalJSON() ([]byte, error) { }) } +func (r PermissionDecisionCancelled) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionCancelled + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionDeniedByContentExclusionPolicy) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionDeniedByContentExclusionPolicy + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionDeniedByPermissionRequestHook) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionDeniedByPermissionRequestHook + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionDeniedByRules) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionDeniedByRules + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionDeniedInteractivelyByUser) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionDeniedInteractivelyByUser + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + +func (r PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser) MarshalJSON() ([]byte, error) { + type alias PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser + return json.Marshal(struct { + Kind PermissionDecisionKind `json:"kind"` + alias + }{ + Kind: r.Kind(), + alias: alias(r), + }) +} + func (r PermissionDecisionReject) MarshalJSON() ([]byte, error) { type alias PermissionDecisionReject return json.Marshal(struct { @@ -1122,6 +1710,235 @@ func (r *PermissionDecisionRequest) UnmarshalJSON(data []byte) error { return nil } +func unmarshalSendAttachment(data []byte) (SendAttachment, error) { + if string(data) == "null" { + return nil, nil + } + type rawUnion struct { + Type SendAttachmentType `json:"type"` + } + var raw rawUnion + if err := json.Unmarshal(data, &raw); err != nil { + return nil, err + } + + switch raw.Type { + case SendAttachmentTypeBlob: + var d SendAttachmentBlob + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case SendAttachmentTypeDirectory: + var d SendAttachmentDirectory + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case SendAttachmentTypeFile: + var d SendAttachmentFile + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case SendAttachmentTypeGithubReference: + var d SendAttachmentGithubReference + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case SendAttachmentTypeSelection: + var d SendAttachmentSelection + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + default: + return &RawSendAttachmentData{Discriminator: raw.Type, Raw: data}, nil + } +} + +func (r RawSendAttachmentData) MarshalJSON() ([]byte, error) { + if r.Raw != nil { + return r.Raw, nil + } + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + }{ + Type: r.Discriminator, + }) +} + +func (r SendAttachmentBlob) MarshalJSON() ([]byte, error) { + type alias SendAttachmentBlob + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r SendAttachmentDirectory) MarshalJSON() ([]byte, error) { + type alias SendAttachmentDirectory + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r SendAttachmentFile) MarshalJSON() ([]byte, error) { + type alias SendAttachmentFile + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r SendAttachmentGithubReference) MarshalJSON() ([]byte, error) { + type alias SendAttachmentGithubReference + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r SendAttachmentSelection) MarshalJSON() ([]byte, error) { + type alias SendAttachmentSelection + return json.Marshal(struct { + Type SendAttachmentType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r *SendRequest) UnmarshalJSON(data []byte) error { + type rawSendRequest struct { + AgentMode *SendAgentMode `json:"agentMode,omitempty"` + Attachments []json.RawMessage `json:"attachments,omitempty"` + Billable *bool `json:"billable,omitempty"` + DisplayPrompt *string `json:"displayPrompt,omitempty"` + Mode *SendMode `json:"mode,omitempty"` + Prepend *bool `json:"prepend,omitempty"` + Prompt string `json:"prompt"` + RequestHeaders map[string]string `json:"requestHeaders,omitempty"` + RequiredTool *string `json:"requiredTool,omitempty"` + Source any `json:"source,omitempty"` + Traceparent *string `json:"traceparent,omitempty"` + Tracestate *string `json:"tracestate,omitempty"` + Wait *bool `json:"wait,omitempty"` + } + var raw rawSendRequest + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + r.AgentMode = raw.AgentMode + if raw.Attachments != nil { + r.Attachments = make([]SendAttachment, 0, len(raw.Attachments)) + for _, rawItem := range raw.Attachments { + value, err := unmarshalSendAttachment(rawItem) + if err != nil { + return err + } + r.Attachments = append(r.Attachments, value) + } + } + r.Billable = raw.Billable + r.DisplayPrompt = raw.DisplayPrompt + r.Mode = raw.Mode + r.Prepend = raw.Prepend + r.Prompt = raw.Prompt + r.RequestHeaders = raw.RequestHeaders + r.RequiredTool = raw.RequiredTool + r.Source = raw.Source + r.Traceparent = raw.Traceparent + r.Tracestate = raw.Tracestate + r.Wait = raw.Wait + return nil +} + +func (r SessionInstalledPluginSource) MarshalJSON() ([]byte, error) { + if r.SessionInstalledPluginSourceGithub != nil { + return json.Marshal(r.SessionInstalledPluginSourceGithub) + } + if r.SessionInstalledPluginSourceLocal != nil { + return json.Marshal(r.SessionInstalledPluginSourceLocal) + } + if r.SessionInstalledPluginSourceURL != nil { + return json.Marshal(r.SessionInstalledPluginSourceURL) + } + if r.String != nil { + return json.Marshal(r.String) + } + return []byte("null"), nil +} + +func (r *SessionInstalledPluginSource) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + *r = SessionInstalledPluginSource{} + return nil + } + { + var value SessionInstalledPluginSourceGithub + if err := json.Unmarshal(data, &value); err == nil { + *r = SessionInstalledPluginSource{SessionInstalledPluginSourceGithub: &value} + return nil + } + } + { + var value SessionInstalledPluginSourceLocal + if err := json.Unmarshal(data, &value); err == nil { + *r = SessionInstalledPluginSource{SessionInstalledPluginSourceLocal: &value} + return nil + } + } + { + var value SessionInstalledPluginSourceURL + if err := json.Unmarshal(data, &value); err == nil { + *r = SessionInstalledPluginSource{SessionInstalledPluginSourceURL: &value} + return nil + } + } + { + var value string + if err := json.Unmarshal(data, &value); err == nil { + *r = SessionInstalledPluginSource{String: &value} + return nil + } + } + return errors.New("data did not match any union variant for SessionInstalledPluginSource") +} + +func (r *SessionSetCredentialsParams) UnmarshalJSON(data []byte) error { + type rawSessionSetCredentialsParams struct { + Credentials json.RawMessage `json:"credentials,omitempty"` + } + var raw rawSessionSetCredentialsParams + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + if raw.Credentials != nil { + value, err := unmarshalAuthInfo(raw.Credentials) + if err != nil { + return err + } + r.Credentials = value + } + return nil +} + func unmarshalSlashCommandInvocationResult(data []byte) (SlashCommandInvocationResult, error) { if string(data) == "null" { return nil, nil @@ -1202,6 +2019,69 @@ func (r SlashCommandTextResult) MarshalJSON() ([]byte, error) { }) } +func unmarshalTaskAgentProgress(data []byte) (TaskAgentProgress, error) { + if string(data) == "null" { + return nil, nil + } + type rawUnion struct { + Type TaskAgentProgressType `json:"type"` + } + var raw rawUnion + if err := json.Unmarshal(data, &raw); err != nil { + return nil, err + } + + switch raw.Type { + case TaskAgentProgressTypeAgent: + var d TaskAgentProgressAgent + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + case TaskAgentProgressTypeShell: + var d TaskAgentProgressShell + if err := json.Unmarshal(data, &d); err != nil { + return nil, err + } + return &d, nil + default: + return &RawTaskAgentProgressData{Discriminator: raw.Type, Raw: data}, nil + } +} + +func (r RawTaskAgentProgressData) MarshalJSON() ([]byte, error) { + if r.Raw != nil { + return r.Raw, nil + } + return json.Marshal(struct { + Type TaskAgentProgressType `json:"type"` + }{ + Type: r.Discriminator, + }) +} + +func (r TaskAgentProgressAgent) MarshalJSON() ([]byte, error) { + type alias TaskAgentProgressAgent + return json.Marshal(struct { + Type TaskAgentProgressType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + +func (r TaskAgentProgressShell) MarshalJSON() ([]byte, error) { + type alias TaskAgentProgressShell + return json.Marshal(struct { + Type TaskAgentProgressType `json:"type"` + alias + }{ + Type: r.Type(), + alias: alias(r), + }) +} + func unmarshalTaskInfo(data []byte) (TaskInfo, error) { if string(data) == "null" { return nil, nil @@ -1286,6 +2166,74 @@ func (r *TaskList) UnmarshalJSON(data []byte) error { return nil } +func (r TaskProgress) MarshalJSON() ([]byte, error) { + if r.TaskAgentProgress != nil { + return json.Marshal(r.TaskAgentProgress) + } + if r.TaskShellProgress != nil { + return json.Marshal(r.TaskShellProgress) + } + return []byte("null"), nil +} + +func (r *TaskProgress) UnmarshalJSON(data []byte) error { + if string(data) == "null" { + *r = TaskProgress{} + return nil + } + { + var value TaskAgentProgress + if err := json.Unmarshal(data, &value); err == nil { + *r = TaskProgress{TaskAgentProgress: value} + return nil + } + } + { + var value any + if err := json.Unmarshal(data, &value); err == nil { + *r = TaskProgress{TaskShellProgress: &value} + return nil + } + } + return errors.New("data did not match any union variant for TaskProgress") +} + +func (r *TasksGetCurrentPromotableResult) UnmarshalJSON(data []byte) error { + type rawTasksGetCurrentPromotableResult struct { + Task json.RawMessage `json:"task,omitempty"` + } + var raw rawTasksGetCurrentPromotableResult + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + if raw.Task != nil { + value, err := unmarshalTaskInfo(raw.Task) + if err != nil { + return err + } + r.Task = value + } + return nil +} + +func (r *TasksPromoteCurrentToBackgroundResult) UnmarshalJSON(data []byte) error { + type rawTasksPromoteCurrentToBackgroundResult struct { + Task json.RawMessage `json:"task,omitempty"` + } + var raw rawTasksPromoteCurrentToBackgroundResult + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + if raw.Task != nil { + value, err := unmarshalTaskInfo(raw.Task) + if err != nil { + return err + } + r.Task = value + } + return nil +} + func unmarshalUIElicitationFieldValue(data []byte) (UIElicitationFieldValue, error) { if string(data) == "null" { return nil, nil diff --git a/go/rpc/zsession_encoding.go b/go/rpc/zsession_encoding.go index 3e89f210a..cc61228ab 100644 --- a/go/rpc/zsession_encoding.go +++ b/go/rpc/zsession_encoding.go @@ -1617,191 +1617,6 @@ func (r PermissionApproved) MarshalJSON() ([]byte, error) { }) } -func unmarshalUserToolSessionApproval(data []byte) (UserToolSessionApproval, error) { - if string(data) == "null" { - return nil, nil - } - type rawUnion struct { - Kind UserToolSessionApprovalKind `json:"kind"` - } - var raw rawUnion - if err := json.Unmarshal(data, &raw); err != nil { - return nil, err - } - - switch raw.Kind { - case UserToolSessionApprovalKindCommands: - var d UserToolSessionApprovalCommands - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindCustomTool: - var d UserToolSessionApprovalCustomTool - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindExtensionManagement: - var d UserToolSessionApprovalExtensionManagement - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindExtensionPermissionAccess: - var d UserToolSessionApprovalExtensionPermissionAccess - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindMcp: - var d UserToolSessionApprovalMcp - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindMemory: - var d UserToolSessionApprovalMemory - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindRead: - var d UserToolSessionApprovalRead - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - case UserToolSessionApprovalKindWrite: - var d UserToolSessionApprovalWrite - if err := json.Unmarshal(data, &d); err != nil { - return nil, err - } - return &d, nil - default: - return &RawUserToolSessionApproval{Discriminator: raw.Kind, Raw: data}, nil - } -} - -func (r RawUserToolSessionApproval) MarshalJSON() ([]byte, error) { - if r.Raw != nil { - return r.Raw, nil - } - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - }{ - Kind: r.Discriminator, - }) -} - -func (r UserToolSessionApprovalCommands) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalCommands - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalCustomTool) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalCustomTool - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalExtensionManagement) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalExtensionManagement - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalExtensionPermissionAccess) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalExtensionPermissionAccess - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalMcp) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalMcp - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalMemory) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalMemory - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalRead) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalRead - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r UserToolSessionApprovalWrite) MarshalJSON() ([]byte, error) { - type alias UserToolSessionApprovalWrite - return json.Marshal(struct { - Kind UserToolSessionApprovalKind `json:"kind"` - alias - }{ - Kind: r.Kind(), - alias: alias(r), - }) -} - -func (r *PermissionApprovedForLocation) UnmarshalJSON(data []byte) error { - type rawPermissionApprovedForLocation struct { - Approval json.RawMessage `json:"approval"` - LocationKey string `json:"locationKey"` - } - var raw rawPermissionApprovedForLocation - if err := json.Unmarshal(data, &raw); err != nil { - return err - } - if raw.Approval != nil { - value, err := unmarshalUserToolSessionApproval(raw.Approval) - if err != nil { - return err - } - r.Approval = value - } - r.LocationKey = raw.LocationKey - return nil -} - func (r PermissionApprovedForLocation) MarshalJSON() ([]byte, error) { type alias PermissionApprovedForLocation return json.Marshal(struct { @@ -1813,24 +1628,6 @@ func (r PermissionApprovedForLocation) MarshalJSON() ([]byte, error) { }) } -func (r *PermissionApprovedForSession) UnmarshalJSON(data []byte) error { - type rawPermissionApprovedForSession struct { - Approval json.RawMessage `json:"approval"` - } - var raw rawPermissionApprovedForSession - if err := json.Unmarshal(data, &raw); err != nil { - return err - } - if raw.Approval != nil { - value, err := unmarshalUserToolSessionApproval(raw.Approval) - if err != nil { - return err - } - r.Approval = value - } - return nil -} - func (r PermissionApprovedForSession) MarshalJSON() ([]byte, error) { type alias PermissionApprovedForSession return json.Marshal(struct { diff --git a/go/rpc/zsession_events.go b/go/rpc/zsession_events.go index 15e7088ea..5cd1d2ae0 100644 --- a/go/rpc/zsession_events.go +++ b/go/rpc/zsession_events.go @@ -184,7 +184,7 @@ type AssistantMessageData struct { // Model that produced this assistant message, if known Model *string `json:"model,omitempty"` // Actual output token count from the API response (completion_tokens), used for accurate token accounting - OutputTokens *float64 `json:"outputTokens,omitempty"` + OutputTokens *int64 `json:"outputTokens,omitempty"` // Tool call ID of the parent tool invocation when this event originates from a sub-agent // Deprecated: ParentToolCallID is deprecated. ParentToolCallID *string `json:"parentToolCallId,omitempty"` @@ -225,7 +225,7 @@ type AutoModeSwitchRequestedData struct { // Unique identifier for this request; used to respond via session.respondToAutoModeSwitch() RequestID string `json:"requestId"` // Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt. - RetryAfterSeconds *float64 `json:"retryAfterSeconds,omitempty"` + RetryAfterSeconds *int64 `json:"retryAfterSeconds,omitempty"` } func (*AutoModeSwitchRequestedData) sessionEventData() {} @@ -236,11 +236,11 @@ func (*AutoModeSwitchRequestedData) Type() SessionEventType { // Context window breakdown at the start of LLM-powered conversation compaction type SessionCompactionStartData struct { // Token count from non-system messages (user, assistant, tool) at compaction start - ConversationTokens *float64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Token count from system message(s) at compaction start - SystemTokens *float64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Token count from tool definitions at compaction start - ToolDefinitionsTokens *float64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } func (*SessionCompactionStartData) sessionEventData() {} @@ -251,23 +251,23 @@ func (*SessionCompactionStartData) Type() SessionEventType { // Conversation compaction results including success status, metrics, and optional error details type SessionCompactionCompleteData struct { // Checkpoint snapshot number created for recovery - CheckpointNumber *float64 `json:"checkpointNumber,omitempty"` + CheckpointNumber *int64 `json:"checkpointNumber,omitempty"` // File path where the checkpoint was stored CheckpointPath *string `json:"checkpointPath,omitempty"` // Token usage breakdown for the compaction LLM call (aligned with assistant.usage format) CompactionTokensUsed *CompactionCompleteCompactionTokensUsed `json:"compactionTokensUsed,omitempty"` // Token count from non-system messages (user, assistant, tool) after compaction - ConversationTokens *float64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Error message if compaction failed Error *string `json:"error,omitempty"` // Number of messages removed during compaction - MessagesRemoved *float64 `json:"messagesRemoved,omitempty"` + MessagesRemoved *int64 `json:"messagesRemoved,omitempty"` // Total tokens in conversation after compaction - PostCompactionTokens *float64 `json:"postCompactionTokens,omitempty"` + PostCompactionTokens *int64 `json:"postCompactionTokens,omitempty"` // Number of messages before compaction - PreCompactionMessagesLength *float64 `json:"preCompactionMessagesLength,omitempty"` + PreCompactionMessagesLength *int64 `json:"preCompactionMessagesLength,omitempty"` // Total tokens in conversation before compaction - PreCompactionTokens *float64 `json:"preCompactionTokens,omitempty"` + PreCompactionTokens *int64 `json:"preCompactionTokens,omitempty"` // GitHub request tracing ID (x-github-request-id header) for the compaction LLM call RequestID *string `json:"requestId,omitempty"` // Whether compaction completed successfully @@ -275,11 +275,11 @@ type SessionCompactionCompleteData struct { // LLM-generated summary of the compacted conversation history SummaryContent *string `json:"summaryContent,omitempty"` // Token count from system message(s) after compaction - SystemTokens *float64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Number of tokens removed during compaction - TokensRemoved *float64 `json:"tokensRemoved,omitempty"` + TokensRemoved *int64 `json:"tokensRemoved,omitempty"` // Token count from tool definitions after compaction - ToolDefinitionsTokens *float64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } func (*SessionCompactionCompleteData) sessionEventData() {} @@ -290,21 +290,21 @@ func (*SessionCompactionCompleteData) Type() SessionEventType { // Conversation truncation statistics including token counts and removed content metrics type SessionTruncationData struct { // Number of messages removed by truncation - MessagesRemovedDuringTruncation float64 `json:"messagesRemovedDuringTruncation"` + MessagesRemovedDuringTruncation int64 `json:"messagesRemovedDuringTruncation"` // Identifier of the component that performed truncation (e.g., "BasicTruncator") PerformedBy string `json:"performedBy"` // Number of conversation messages after truncation - PostTruncationMessagesLength float64 `json:"postTruncationMessagesLength"` + PostTruncationMessagesLength int64 `json:"postTruncationMessagesLength"` // Total tokens in conversation messages after truncation - PostTruncationTokensInMessages float64 `json:"postTruncationTokensInMessages"` + PostTruncationTokensInMessages int64 `json:"postTruncationTokensInMessages"` // Number of conversation messages before truncation - PreTruncationMessagesLength float64 `json:"preTruncationMessagesLength"` + PreTruncationMessagesLength int64 `json:"preTruncationMessagesLength"` // Total tokens in conversation messages before truncation - PreTruncationTokensInMessages float64 `json:"preTruncationTokensInMessages"` + PreTruncationTokensInMessages int64 `json:"preTruncationTokensInMessages"` // Maximum token count for the model's context window - TokenLimit float64 `json:"tokenLimit"` + TokenLimit int64 `json:"tokenLimit"` // Number of tokens removed by truncation - TokensRemovedDuringTruncation float64 `json:"tokensRemovedDuringTruncation"` + TokensRemovedDuringTruncation int64 `json:"tokensRemovedDuringTruncation"` } func (*SessionTruncationData) sessionEventData() {} @@ -313,19 +313,19 @@ func (*SessionTruncationData) Type() SessionEventType { return SessionEventTypeS // Current context window usage statistics including token and message counts type SessionUsageInfoData struct { // Token count from non-system messages (user, assistant, tool) - ConversationTokens *float64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Current number of tokens in the context window - CurrentTokens float64 `json:"currentTokens"` + CurrentTokens int64 `json:"currentTokens"` // Whether this is the first usage_info event emitted in this session IsInitial *bool `json:"isInitial,omitempty"` // Current number of messages in the conversation - MessagesLength float64 `json:"messagesLength"` + MessagesLength int64 `json:"messagesLength"` // Token count from system message(s) - SystemTokens *float64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Maximum token count for the model's context window - TokenLimit float64 `json:"tokenLimit"` + TokenLimit int64 `json:"tokenLimit"` // Token count from tool definitions - ToolDefinitionsTokens *float64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` } func (*SessionUsageInfoData) sessionEventData() {} @@ -409,7 +409,7 @@ type SessionErrorData struct { // Error stack trace, when available Stack *string `json:"stack,omitempty"` // HTTP status code from the upstream request, if applicable - StatusCode *int64 `json:"statusCode,omitempty"` + StatusCode *int32 `json:"statusCode,omitempty"` // Optional URL associated with this error that the user can open in a browser URL *string `json:"url,omitempty"` } @@ -456,7 +456,7 @@ type ModelCallFailureData struct { // Completion ID from the model provider (e.g., chatcmpl-abc123) APICallID *string `json:"apiCallId,omitempty"` // Duration of the failed API call in milliseconds - DurationMs *float64 `json:"durationMs,omitempty"` + DurationMs *int64 `json:"durationMs,omitempty"` // Raw provider/runtime error message for restricted telemetry ErrorMessage *string `json:"errorMessage,omitempty"` // What initiated this API call (e.g., "sub-agent", "mcp-sampling"); absent for user-initiated calls @@ -468,7 +468,7 @@ type ModelCallFailureData struct { // Where the failed model call originated Source ModelCallFailureSource `json:"source"` // HTTP status code from the failed request - StatusCode *int64 `json:"statusCode,omitempty"` + StatusCode *int32 `json:"statusCode,omitempty"` } func (*ModelCallFailureData) sessionEventData() {} @@ -526,25 +526,25 @@ type AssistantUsageData struct { // API endpoint used for this model call, matching CAPI supported_endpoints vocabulary APIEndpoint *AssistantUsageAPIEndpoint `json:"apiEndpoint,omitempty"` // Number of tokens read from prompt cache - CacheReadTokens *float64 `json:"cacheReadTokens,omitempty"` + CacheReadTokens *int64 `json:"cacheReadTokens,omitempty"` // Number of tokens written to prompt cache - CacheWriteTokens *float64 `json:"cacheWriteTokens,omitempty"` + CacheWriteTokens *int64 `json:"cacheWriteTokens,omitempty"` // Per-request cost and usage data from the CAPI copilot_usage response field CopilotUsage *AssistantUsageCopilotUsage `json:"copilotUsage,omitempty"` // Model multiplier cost for billing purposes Cost *float64 `json:"cost,omitempty"` // Duration of the API call in milliseconds - Duration *float64 `json:"duration,omitempty"` + Duration *int64 `json:"duration,omitempty"` // What initiated this API call (e.g., "sub-agent", "mcp-sampling"); absent for user-initiated calls Initiator *string `json:"initiator,omitempty"` // Number of input tokens consumed - InputTokens *float64 `json:"inputTokens,omitempty"` + InputTokens *int64 `json:"inputTokens,omitempty"` // Average inter-token latency in milliseconds. Only available for streaming requests InterTokenLatencyMs *float64 `json:"interTokenLatencyMs,omitempty"` // Model identifier used for this API call Model string `json:"model"` // Number of output tokens produced - OutputTokens *float64 `json:"outputTokens,omitempty"` + OutputTokens *int64 `json:"outputTokens,omitempty"` // Parent tool call ID when this usage originates from a sub-agent // Deprecated: ParentToolCallID is deprecated. ParentToolCallID *string `json:"parentToolCallId,omitempty"` @@ -555,9 +555,9 @@ type AssistantUsageData struct { // Reasoning effort level used for model calls, if applicable (e.g. "none", "low", "medium", "high", "xhigh", "max") ReasoningEffort *string `json:"reasoningEffort,omitempty"` // Number of output tokens used for reasoning (e.g., chain-of-thought) - ReasoningTokens *float64 `json:"reasoningTokens,omitempty"` + ReasoningTokens *int64 `json:"reasoningTokens,omitempty"` // Time to first token in milliseconds. Only available for streaming requests - TtftMs *float64 `json:"ttftMs,omitempty"` + TtftMs *int64 `json:"ttftMs,omitempty"` } func (*AssistantUsageData) sessionEventData() {} @@ -907,7 +907,7 @@ type UserMessageData struct { InteractionID *string `json:"interactionId,omitempty"` // True when this user message was auto-injected by autopilot's continuation loop rather than typed by the user; used to distinguish autopilot-driven turns in telemetry. IsAutopilotContinuation *bool `json:"isAutopilotContinuation,omitempty"` - // Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit + // Path-backed native document attachments that stayed on the tagged_files path flow because native upload could not read them or would exceed the request size limit NativeDocumentPathFallbackPaths []string `json:"nativeDocumentPathFallbackPaths,omitempty"` // Parent agent task ID for background telemetry correlated to this user turn ParentAgentTaskID *string `json:"parentAgentTaskId,omitempty"` @@ -977,7 +977,7 @@ type SessionStartData struct { // ISO 8601 timestamp when the session was created StartTime time.Time `json:"startTime"` // Schema version number for the session event format - Version float64 `json:"version"` + Version int64 `json:"version"` } func (*SessionStartData) sessionEventData() {} @@ -992,7 +992,7 @@ type SessionResumeData struct { // When true, tool calls and permission requests left in flight by the previous session lifetime remain pending after resume and the agentic loop awaits their results. User sends are queued behind the pending work until all such requests reach a terminal state. When false (the default), any such tool calls and permission requests are immediately marked as interrupted on resume. ContinuePendingWork *bool `json:"continuePendingWork,omitempty"` // Total number of persisted events in the session at the time of resume - EventCount float64 `json:"eventCount"` + EventCount int64 `json:"eventCount"` // Reasoning effort level used for model calls, if applicable (e.g. "none", "low", "medium", "high", "xhigh", "max") ReasoningEffort *string `json:"reasoningEffort,omitempty"` // Reasoning summary mode used for model calls, if applicable (e.g. "none", "concise", "detailed") @@ -1013,7 +1013,7 @@ func (*SessionResumeData) Type() SessionEventType { return SessionEventTypeSessi // Session rewind details including target event and count of removed events type SessionSnapshotRewindData struct { // Number of events that were removed by the rewind - EventsRemoved float64 `json:"eventsRemoved"` + EventsRemoved int64 `json:"eventsRemoved"` // Event ID that was rewound to; this event and all after it were removed UpToEventID string `json:"upToEventId"` } @@ -1028,31 +1028,31 @@ type SessionShutdownData struct { // Aggregate code change metrics for the session CodeChanges ShutdownCodeChanges `json:"codeChanges"` // Non-system message token count at shutdown - ConversationTokens *float64 `json:"conversationTokens,omitempty"` + ConversationTokens *int64 `json:"conversationTokens,omitempty"` // Model that was selected at the time of shutdown CurrentModel *string `json:"currentModel,omitempty"` // Total tokens in context window at shutdown - CurrentTokens *float64 `json:"currentTokens,omitempty"` + CurrentTokens *int64 `json:"currentTokens,omitempty"` // Error description when shutdownType is "error" ErrorReason *string `json:"errorReason,omitempty"` // Per-model usage breakdown, keyed by model identifier ModelMetrics map[string]ShutdownModelMetric `json:"modelMetrics"` // Unix timestamp (milliseconds) when the session started - SessionStartTime float64 `json:"sessionStartTime"` + SessionStartTime int64 `json:"sessionStartTime"` // Whether the session ended normally ("routine") or due to a crash/fatal error ("error") ShutdownType ShutdownType `json:"shutdownType"` // System message token count at shutdown - SystemTokens *float64 `json:"systemTokens,omitempty"` + SystemTokens *int64 `json:"systemTokens,omitempty"` // Session-wide per-token-type accumulated token counts TokenDetails map[string]ShutdownTokenDetail `json:"tokenDetails,omitempty"` // Tool definitions token count at shutdown - ToolDefinitionsTokens *float64 `json:"toolDefinitionsTokens,omitempty"` + ToolDefinitionsTokens *int64 `json:"toolDefinitionsTokens,omitempty"` // Cumulative time spent in API calls during the session, in milliseconds - TotalAPIDurationMs float64 `json:"totalApiDurationMs"` + TotalAPIDurationMs int64 `json:"totalApiDurationMs"` // Session-wide accumulated nano-AI units cost - TotalNanoAiu *float64 `json:"totalNanoAiu,omitempty"` + TotalNanoAiu *int64 `json:"totalNanoAiu,omitempty"` // Total number of premium API requests used during the session - TotalPremiumRequests float64 `json:"totalPremiumRequests"` + TotalPremiumRequests int64 `json:"totalPremiumRequests"` } func (*SessionShutdownData) sessionEventData() {} @@ -1133,7 +1133,7 @@ func (*AssistantReasoningDeltaData) Type() SessionEventType { // Streaming response progress with cumulative byte count type AssistantStreamingDeltaData struct { // Cumulative total bytes received from the streaming response so far - TotalResponseSizeBytes float64 `json:"totalResponseSizeBytes"` + TotalResponseSizeBytes int64 `json:"totalResponseSizeBytes"` } func (*AssistantStreamingDeltaData) sessionEventData() {} @@ -1161,15 +1161,15 @@ type SubagentCompletedData struct { // Internal name of the sub-agent AgentName string `json:"agentName"` // Wall-clock duration of the sub-agent execution in milliseconds - DurationMs *float64 `json:"durationMs,omitempty"` + DurationMs *int64 `json:"durationMs,omitempty"` // Model used by the sub-agent Model *string `json:"model,omitempty"` // Tool call ID of the parent tool invocation that spawned this sub-agent ToolCallID string `json:"toolCallId"` // Total tokens (input + output) consumed by the sub-agent - TotalTokens *float64 `json:"totalTokens,omitempty"` + TotalTokens *int64 `json:"totalTokens,omitempty"` // Total number of tool calls made by the sub-agent - TotalToolCalls *float64 `json:"totalToolCalls,omitempty"` + TotalToolCalls *int64 `json:"totalToolCalls,omitempty"` } func (*SubagentCompletedData) sessionEventData() {} @@ -1182,7 +1182,7 @@ type SubagentFailedData struct { // Internal name of the sub-agent AgentName string `json:"agentName"` // Wall-clock duration of the sub-agent execution in milliseconds - DurationMs *float64 `json:"durationMs,omitempty"` + DurationMs *int64 `json:"durationMs,omitempty"` // Error message describing why the sub-agent failed Error string `json:"error"` // Model used by the sub-agent (if any model calls succeeded before failure) @@ -1190,9 +1190,9 @@ type SubagentFailedData struct { // Tool call ID of the parent tool invocation that spawned this sub-agent ToolCallID string `json:"toolCallId"` // Total tokens (input + output) consumed before the sub-agent failed - TotalTokens *float64 `json:"totalTokens,omitempty"` + TotalTokens *int64 `json:"totalTokens,omitempty"` // Total number of tool calls made before the sub-agent failed - TotalToolCalls *float64 `json:"totalToolCalls,omitempty"` + TotalToolCalls *int64 `json:"totalToolCalls,omitempty"` } func (*SubagentFailedData) sessionEventData() {} @@ -1465,17 +1465,17 @@ type AssistantUsageCopilotUsage struct { // Itemized token usage breakdown TokenDetails []AssistantUsageCopilotUsageTokenDetail `json:"tokenDetails"` // Total cost in nano-AI units for this request - TotalNanoAiu float64 `json:"totalNanoAiu"` + TotalNanoAiu int64 `json:"totalNanoAiu"` } // Token usage detail for a single billing category type AssistantUsageCopilotUsageTokenDetail struct { // Number of tokens in this billing batch - BatchSize float64 `json:"batchSize"` + BatchSize int64 `json:"batchSize"` // Cost per batch of tokens - CostPerBatch float64 `json:"costPerBatch"` + CostPerBatch int64 `json:"costPerBatch"` // Total token count for this entry - TokenCount float64 `json:"tokenCount"` + TokenCount int64 `json:"tokenCount"` // Token category (e.g., "input", "output") TokenType string `json:"tokenType"` } @@ -1483,21 +1483,21 @@ type AssistantUsageCopilotUsageTokenDetail struct { // Schema for the `AssistantUsageQuotaSnapshot` type. type AssistantUsageQuotaSnapshot struct { // Total requests allowed by the entitlement - EntitlementRequests float64 `json:"entitlementRequests"` + EntitlementRequests int64 `json:"entitlementRequests"` // Whether the user has an unlimited usage entitlement IsUnlimitedEntitlement bool `json:"isUnlimitedEntitlement"` // Number of requests over the entitlement limit Overage float64 `json:"overage"` // Whether overage is allowed when quota is exhausted OverageAllowedWithExhaustedQuota bool `json:"overageAllowedWithExhaustedQuota"` - // Percentage of quota remaining (0.0 to 1.0) + // Percentage of quota remaining (0 to 100) RemainingPercentage float64 `json:"remainingPercentage"` // Date when the quota resets ResetDate *time.Time `json:"resetDate,omitempty"` // Whether usage is still permitted after quota exhaustion UsageAllowedWithExhaustedQuota bool `json:"usageAllowedWithExhaustedQuota"` // Number of requests already consumed - UsedRequests float64 `json:"usedRequests"` + UsedRequests int64 `json:"usedRequests"` } // UI capability changes @@ -1517,19 +1517,19 @@ type CommandsChangedCommand struct { // Token usage breakdown for the compaction LLM call (aligned with assistant.usage format) type CompactionCompleteCompactionTokensUsed struct { // Cached input tokens reused in the compaction LLM call - CacheReadTokens *float64 `json:"cacheReadTokens,omitempty"` + CacheReadTokens *int64 `json:"cacheReadTokens,omitempty"` // Tokens written to prompt cache in the compaction LLM call - CacheWriteTokens *float64 `json:"cacheWriteTokens,omitempty"` + CacheWriteTokens *int64 `json:"cacheWriteTokens,omitempty"` // Per-request cost and usage data from the CAPI copilot_usage response field CopilotUsage *CompactionCompleteCompactionTokensUsedCopilotUsage `json:"copilotUsage,omitempty"` // Duration of the compaction LLM call in milliseconds - Duration *float64 `json:"duration,omitempty"` + Duration *int64 `json:"duration,omitempty"` // Input tokens consumed by the compaction LLM call - InputTokens *float64 `json:"inputTokens,omitempty"` + InputTokens *int64 `json:"inputTokens,omitempty"` // Model identifier used for the compaction LLM call Model *string `json:"model,omitempty"` // Output tokens produced by the compaction LLM call - OutputTokens *float64 `json:"outputTokens,omitempty"` + OutputTokens *int64 `json:"outputTokens,omitempty"` } // Per-request cost and usage data from the CAPI copilot_usage response field @@ -1537,17 +1537,17 @@ type CompactionCompleteCompactionTokensUsedCopilotUsage struct { // Itemized token usage breakdown TokenDetails []CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail `json:"tokenDetails"` // Total cost in nano-AI units for this request - TotalNanoAiu float64 `json:"totalNanoAiu"` + TotalNanoAiu int64 `json:"totalNanoAiu"` } // Token usage detail for a single billing category type CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail struct { // Number of tokens in this billing batch - BatchSize float64 `json:"batchSize"` + BatchSize int64 `json:"batchSize"` // Cost per batch of tokens - CostPerBatch float64 `json:"costPerBatch"` + CostPerBatch int64 `json:"costPerBatch"` // Total token count for this entry - TokenCount float64 `json:"tokenCount"` + TokenCount int64 `json:"tokenCount"` // Token category (e.g., "input", "output") TokenType string `json:"tokenType"` } @@ -2208,22 +2208,14 @@ func (PermissionDeniedNoApprovalRuleAndCouldNotRequestFromUser) Kind() Permissio return PermissionResultKindDeniedNoApprovalRuleAndCouldNotRequestFromUser } -// Schema for the `PermissionRule` type. -type PermissionRule struct { - // Optional rule argument matched against the request - Argument *string `json:"argument"` - // The rule kind, such as Shell or GitHubMCP - Kind string `json:"kind"` -} - // Aggregate code change metrics for the session type ShutdownCodeChanges struct { // List of file paths that were modified during the session FilesModified []string `json:"filesModified"` // Total number of lines added during the session - LinesAdded float64 `json:"linesAdded"` + LinesAdded int64 `json:"linesAdded"` // Total number of lines removed during the session - LinesRemoved float64 `json:"linesRemoved"` + LinesRemoved int64 `json:"linesRemoved"` } // Schema for the `ShutdownModelMetric` type. @@ -2233,7 +2225,7 @@ type ShutdownModelMetric struct { // Token count details per type TokenDetails map[string]ShutdownModelMetricTokenDetail `json:"tokenDetails,omitempty"` // Accumulated nano-AI units cost for this model - TotalNanoAiu *float64 `json:"totalNanoAiu,omitempty"` + TotalNanoAiu *int64 `json:"totalNanoAiu,omitempty"` // Token usage breakdown Usage ShutdownModelMetricUsage `json:"usage"` } @@ -2243,33 +2235,33 @@ type ShutdownModelMetricRequests struct { // Cumulative cost multiplier for requests to this model Cost float64 `json:"cost"` // Total number of API requests made to this model - Count float64 `json:"count"` + Count int64 `json:"count"` } // Schema for the `ShutdownModelMetricTokenDetail` type. type ShutdownModelMetricTokenDetail struct { // Accumulated token count for this token type - TokenCount float64 `json:"tokenCount"` + TokenCount int64 `json:"tokenCount"` } // Token usage breakdown type ShutdownModelMetricUsage struct { // Total tokens read from prompt cache across all requests - CacheReadTokens float64 `json:"cacheReadTokens"` + CacheReadTokens int64 `json:"cacheReadTokens"` // Total tokens written to prompt cache across all requests - CacheWriteTokens float64 `json:"cacheWriteTokens"` + CacheWriteTokens int64 `json:"cacheWriteTokens"` // Total input tokens consumed across all requests to this model - InputTokens float64 `json:"inputTokens"` + InputTokens int64 `json:"inputTokens"` // Total output tokens produced across all requests to this model - OutputTokens float64 `json:"outputTokens"` + OutputTokens int64 `json:"outputTokens"` // Total reasoning tokens produced across all requests to this model - ReasoningTokens *float64 `json:"reasoningTokens,omitempty"` + ReasoningTokens *int64 `json:"reasoningTokens,omitempty"` } // Schema for the `ShutdownTokenDetail` type. type ShutdownTokenDetail struct { // Accumulated token count for this token type - TokenCount float64 `json:"tokenCount"` + TokenCount int64 `json:"tokenCount"` } // Schema for the `SkillsLoadedSkill` type. @@ -2385,7 +2377,7 @@ type SystemNotificationShellCompleted struct { // Human-readable description of the command Description *string `json:"description,omitempty"` // Exit code of the shell command, if available - ExitCode *float64 `json:"exitCode,omitempty"` + ExitCode *int64 `json:"exitCode,omitempty"` // Unique identifier of the shell session ShellID string `json:"shellId"` } @@ -2472,7 +2464,7 @@ type ToolExecutionCompleteContentResourceLink struct { // Resource name identifier Name string `json:"name"` // Size of the resource in bytes - Size *float64 `json:"size,omitempty"` + Size *int64 `json:"size,omitempty"` // Human-readable display title for the resource Title *string `json:"title,omitempty"` // URI identifying the resource @@ -2489,7 +2481,7 @@ type ToolExecutionCompleteContentTerminal struct { // Working directory where the command was executed Cwd *string `json:"cwd,omitempty"` // Process exit code, if the command has completed - ExitCode *float64 `json:"exitCode,omitempty"` + ExitCode *int64 `json:"exitCode,omitempty"` // Terminal/shell output text Text string `json:"text"` } @@ -2608,7 +2600,7 @@ func (UserMessageAttachmentFile) Type() UserMessageAttachmentType { // GitHub issue, pull request, or discussion reference type UserMessageAttachmentGithubReference struct { // Issue, pull request, or discussion number - Number float64 `json:"number"` + Number int64 `json:"number"` // Type of GitHub reference ReferenceType UserMessageAttachmentGithubReferenceType `json:"referenceType"` // Current state of the referenced item (e.g., open, closed, merged) @@ -2644,9 +2636,9 @@ func (UserMessageAttachmentSelection) Type() UserMessageAttachmentType { // Optional line range to scope the attachment to a specific section of the file type UserMessageAttachmentFileLineRange struct { // End line number (1-based, inclusive) - End float64 `json:"end"` + End int64 `json:"end"` // Start line number (1-based) - Start float64 `json:"start"` + Start int64 `json:"start"` } // Position range of the selection within the file @@ -2660,117 +2652,17 @@ type UserMessageAttachmentSelectionDetails struct { // End position of the selection type UserMessageAttachmentSelectionDetailsEnd struct { // End character offset within the line (0-based) - Character float64 `json:"character"` + Character int64 `json:"character"` // End line number (0-based) - Line float64 `json:"line"` + Line int64 `json:"line"` } // Start position of the selection type UserMessageAttachmentSelectionDetailsStart struct { // Start character offset within the line (0-based) - Character float64 `json:"character"` + Character int64 `json:"character"` // Start line number (0-based) - Line float64 `json:"line"` -} - -// The approval to add as a session-scoped rule -type UserToolSessionApproval interface { - userToolSessionApproval() - Kind() UserToolSessionApprovalKind -} - -type RawUserToolSessionApproval struct { - Discriminator UserToolSessionApprovalKind - Raw json.RawMessage -} - -func (RawUserToolSessionApproval) userToolSessionApproval() {} -func (r RawUserToolSessionApproval) Kind() UserToolSessionApprovalKind { - return r.Discriminator -} - -// Schema for the `UserToolSessionApprovalCommands` type. -type UserToolSessionApprovalCommands struct { - // Command identifiers approved by the user - CommandIdentifiers []string `json:"commandIdentifiers"` -} - -func (UserToolSessionApprovalCommands) userToolSessionApproval() {} -func (UserToolSessionApprovalCommands) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindCommands -} - -// Schema for the `UserToolSessionApprovalCustomTool` type. -type UserToolSessionApprovalCustomTool struct { - // Custom tool name - ToolName string `json:"toolName"` -} - -func (UserToolSessionApprovalCustomTool) userToolSessionApproval() {} -func (UserToolSessionApprovalCustomTool) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindCustomTool -} - -// Schema for the `UserToolSessionApprovalExtensionManagement` type. -type UserToolSessionApprovalExtensionManagement struct { - // Optional operation identifier - Operation *string `json:"operation,omitempty"` -} - -func (UserToolSessionApprovalExtensionManagement) userToolSessionApproval() {} -func (UserToolSessionApprovalExtensionManagement) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindExtensionManagement -} - -// Schema for the `UserToolSessionApprovalExtensionPermissionAccess` type. -type UserToolSessionApprovalExtensionPermissionAccess struct { - // Extension name - ExtensionName string `json:"extensionName"` -} - -func (UserToolSessionApprovalExtensionPermissionAccess) userToolSessionApproval() {} -func (UserToolSessionApprovalExtensionPermissionAccess) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindExtensionPermissionAccess -} - -// Schema for the `UserToolSessionApprovalMcp` type. -type UserToolSessionApprovalMcp struct { - // MCP server name - ServerName string `json:"serverName"` - // Optional MCP tool name, or null for all tools on the server - ToolName *string `json:"toolName"` -} - -func (UserToolSessionApprovalMcp) userToolSessionApproval() {} -func (UserToolSessionApprovalMcp) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindMcp -} - -// Schema for the `UserToolSessionApprovalMemory` type. -type UserToolSessionApprovalMemory struct { -} - -func (UserToolSessionApprovalMemory) userToolSessionApproval() {} -func (UserToolSessionApprovalMemory) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindMemory -} - -// Schema for the `UserToolSessionApprovalRead` type. -type UserToolSessionApprovalRead struct { -} - -func (UserToolSessionApprovalRead) userToolSessionApproval() {} -func (UserToolSessionApprovalRead) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindRead -} - -// Schema for the `UserToolSessionApprovalWrite` type. -type UserToolSessionApprovalWrite struct { -} - -func (UserToolSessionApprovalWrite) userToolSessionApproval() {} -func (UserToolSessionApprovalWrite) Kind() UserToolSessionApprovalKind { - return UserToolSessionApprovalKindWrite + Line int64 `json:"line"` } // Working directory and git context at session start @@ -2793,15 +2685,6 @@ type WorkingDirectoryContext struct { RepositoryHost *string `json:"repositoryHost,omitempty"` } -// Finite reason code describing why the current turn was aborted -type AbortReason string - -const ( - AbortReasonRemoteCommand AbortReason = "remote_command" - AbortReasonUserAbort AbortReason = "user_abort" - AbortReasonUserInitiated AbortReason = "user_initiated" -) - // Tool call type: "function" for standard tool calls, "custom" for grammar-based tool calls. Defaults to "function" when absent. type AssistantMessageToolRequestType string @@ -2987,14 +2870,6 @@ const ( PlanChangedOperationUpdate PlanChangedOperation = "update" ) -// Whether the session ended normally ("routine") or due to a crash/fatal error ("error") -type ShutdownType string - -const ( - ShutdownTypeError ShutdownType = "error" - ShutdownTypeRoutine ShutdownType = "routine" -) - // Message role: "system" for system prompts, "developer" for developer-injected instructions type SystemMessageRole string @@ -3073,20 +2948,6 @@ const ( UserMessageAttachmentTypeSelection UserMessageAttachmentType = "selection" ) -// Kind discriminator for UserToolSessionApproval. -type UserToolSessionApprovalKind string - -const ( - UserToolSessionApprovalKindCommands UserToolSessionApprovalKind = "commands" - UserToolSessionApprovalKindCustomTool UserToolSessionApprovalKind = "custom-tool" - UserToolSessionApprovalKindExtensionManagement UserToolSessionApprovalKind = "extension-management" - UserToolSessionApprovalKindExtensionPermissionAccess UserToolSessionApprovalKind = "extension-permission-access" - UserToolSessionApprovalKindMcp UserToolSessionApprovalKind = "mcp" - UserToolSessionApprovalKindMemory UserToolSessionApprovalKind = "memory" - UserToolSessionApprovalKindRead UserToolSessionApprovalKind = "read" - UserToolSessionApprovalKindWrite UserToolSessionApprovalKind = "write" -) - // Hosting platform type of the repository (github or ado) type WorkingDirectoryContextHostType string diff --git a/go/zsession_events.go b/go/zsession_events.go index b5ed49a97..b9cd90a83 100644 --- a/go/zsession_events.go +++ b/go/zsession_events.go @@ -132,7 +132,6 @@ type ( RawSystemNotification = rpc.RawSystemNotification RawToolExecutionCompleteContent = rpc.RawToolExecutionCompleteContent RawUserMessageAttachment = rpc.RawUserMessageAttachment - RawUserToolSessionApproval = rpc.RawUserToolSessionApproval ReasoningSummary = rpc.ReasoningSummary SamplingCompletedData = rpc.SamplingCompletedData SamplingRequestedData = rpc.SamplingRequestedData @@ -238,7 +237,6 @@ type ( UserToolSessionApprovalCustomTool = rpc.UserToolSessionApprovalCustomTool UserToolSessionApprovalExtensionManagement = rpc.UserToolSessionApprovalExtensionManagement UserToolSessionApprovalExtensionPermissionAccess = rpc.UserToolSessionApprovalExtensionPermissionAccess - UserToolSessionApprovalKind = rpc.UserToolSessionApprovalKind UserToolSessionApprovalMcp = rpc.UserToolSessionApprovalMcp UserToolSessionApprovalMemory = rpc.UserToolSessionApprovalMemory UserToolSessionApprovalRead = rpc.UserToolSessionApprovalRead @@ -465,14 +463,6 @@ const ( UserMessageAttachmentTypeFile = rpc.UserMessageAttachmentTypeFile UserMessageAttachmentTypeGithubReference = rpc.UserMessageAttachmentTypeGithubReference UserMessageAttachmentTypeSelection = rpc.UserMessageAttachmentTypeSelection - UserToolSessionApprovalKindCommands = rpc.UserToolSessionApprovalKindCommands - UserToolSessionApprovalKindCustomTool = rpc.UserToolSessionApprovalKindCustomTool - UserToolSessionApprovalKindExtensionManagement = rpc.UserToolSessionApprovalKindExtensionManagement - UserToolSessionApprovalKindExtensionPermissionAccess = rpc.UserToolSessionApprovalKindExtensionPermissionAccess - UserToolSessionApprovalKindMcp = rpc.UserToolSessionApprovalKindMcp - UserToolSessionApprovalKindMemory = rpc.UserToolSessionApprovalKindMemory - UserToolSessionApprovalKindRead = rpc.UserToolSessionApprovalKindRead - UserToolSessionApprovalKindWrite = rpc.UserToolSessionApprovalKindWrite WorkingDirectoryContextHostTypeAdo = rpc.WorkingDirectoryContextHostTypeAdo WorkingDirectoryContextHostTypeGithub = rpc.WorkingDirectoryContextHostTypeGithub WorkspaceFileChangedOperationCreate = rpc.WorkspaceFileChangedOperationCreate diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 3dbcc7370..1964c584c 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.8", "license": "MIT", "dependencies": { - "@github/copilot": "^1.0.49", + "@github/copilot": "^1.0.51-1", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, @@ -663,28 +663,28 @@ } }, "node_modules/@github/copilot": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.49.tgz", - "integrity": "sha512-40Udj9uCNXaVT2XYbB93CaA7P/rWdy7DP1r088t11s0chWfm5smm9RDMNRj2KqMywwYw3xgf3ZcTFoTLy7kleA==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.51-1.tgz", + "integrity": "sha512-TCPqoOAf0P6LUk3Xtp7hoO5d1AeGJQMA+Io6wxKeTNzZm6bWf41jFxQPs8Pnzua5vJwBjOid10XhGAVI5gHpFw==", "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.49", - "@github/copilot-darwin-x64": "1.0.49", - "@github/copilot-linux-arm64": "1.0.49", - "@github/copilot-linux-x64": "1.0.49", - "@github/copilot-linuxmusl-arm64": "1.0.49", - "@github/copilot-linuxmusl-x64": "1.0.49", - "@github/copilot-win32-arm64": "1.0.49", - "@github/copilot-win32-x64": "1.0.49" + "@github/copilot-darwin-arm64": "1.0.51-1", + "@github/copilot-darwin-x64": "1.0.51-1", + "@github/copilot-linux-arm64": "1.0.51-1", + "@github/copilot-linux-x64": "1.0.51-1", + "@github/copilot-linuxmusl-arm64": "1.0.51-1", + "@github/copilot-linuxmusl-x64": "1.0.51-1", + "@github/copilot-win32-arm64": "1.0.51-1", + "@github/copilot-win32-x64": "1.0.51-1" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.49.tgz", - "integrity": "sha512-b/qtH1ttG7dnoEC3gLDdrI9n7f5+3LEXD2rOvpdeoxoe8lDlSpUeF4AUpfh7kUivhCKlCIRV+H3+NcRX2rexuQ==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.51-1.tgz", + "integrity": "sha512-IRoWmK7ZGGmOceDpZ/jaGWJULGUVbF0hPuy5CaJsgEdtqD6K/0AfN2wPi+txuOo9H5Q4/iZTZFkoBC3W+moiXQ==", "cpu": [ "arm64" ], @@ -698,9 +698,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.49.tgz", - "integrity": "sha512-hHqoeCKqHttqtX3ZHj2TkAIX6jUg159tHDm7qVLccGotgz5bp6ywFxHyGYs7uwD0D90if/m+s87lXu2xAIkN9A==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.51-1.tgz", + "integrity": "sha512-tIesO+WWTnb5ZlE+l2uq8HNix5og/vV1JhsleXTDR18utVsgJ2Mf4a4nLIF4HXrKWOqJCSEtQHhBESKcOz1oUw==", "cpu": [ "x64" ], @@ -714,9 +714,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.49.tgz", - "integrity": "sha512-faNys7OcjoG6g2vlmOVLgzd4pZPmi0LpZJ0pnOLW6lJ2d9Lk5KsY3aX2g/Uqdoz9oqAPg64t8NH2WPSdHPmBTg==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.51-1.tgz", + "integrity": "sha512-yuiR663dZ28U6i7pKViVMvvJjznXGb8MW/Nw12jeW5Pu2iwnQyb5Mv8YrsrHNs/zSNX+dBkNHEy7sZd/MFkf+w==", "cpu": [ "arm64" ], @@ -730,9 +730,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.49.tgz", - "integrity": "sha512-bMqMoJ2r304yCmzZ+iv9Nf4xS4KdiqNZo+Ld7Iq9y5Rc5T+DVsrgISb9j2rBqtlOe0rdtKhwOuzSc4XP7BDcvw==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.51-1.tgz", + "integrity": "sha512-kx4NUR5qWj8lv+s+uCFQEiPLqddr/8a6ZAJe7h+ENGY/D9+TbP1pvK/nJ3Hjjy+tCpeIKS8+GJl8b1hfihAuXw==", "cpu": [ "x64" ], @@ -746,9 +746,9 @@ } }, "node_modules/@github/copilot-linuxmusl-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.49.tgz", - "integrity": "sha512-j2Ow72hiamC3yU1GQBl4WEAB9okuUxdGCs+bcYxtDSUY144F9i9U9WE8Oil3KP3Je+WLUZSf81OYsHTCM5OjbA==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.51-1.tgz", + "integrity": "sha512-2OijR/pU2U5sMSjntCwmQmdpGDawvT3jaIaEk9FMcCH2m5GJkQFe/WYCAYpoXPJARL/Y+QyY2yybUPUCyX3//A==", "cpu": [ "arm64" ], @@ -762,9 +762,9 @@ } }, "node_modules/@github/copilot-linuxmusl-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.49.tgz", - "integrity": "sha512-/a0iNVqXeEvvm0UyPMjW3UPl0meQSSd8SeaMYkkI2OQkYhlUrd9oaUEJzfYnBgPl37AK5+i73DFy09gSH+Efvw==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.51-1.tgz", + "integrity": "sha512-AHTZUgxzaKQF9XO2HQwwofooJzFLa0gJKN2pE0zCypmTgdyX/B6XV4GCWo3JqBZYwDG29+MtxM0KMDwvzGV3uw==", "cpu": [ "x64" ], @@ -778,9 +778,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.49.tgz", - "integrity": "sha512-2oaOoB47i2EcM1tSO+ay2X7xF29Yc/9LFOqkGZZrdS4gTQvTD3oITQBGwdj5CR3GN9pOFxWrhUvyDf9N77AHFg==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.51-1.tgz", + "integrity": "sha512-iyKSiUf+vj2M8D7WoIeu3QHuAuGCXvxYh8G0QT2CU/8LyLYcZUkGbQtPWqH4WJaSFrH6hCh4vHX8ATIv5ypnQA==", "cpu": [ "arm64" ], @@ -794,9 +794,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.49.tgz", - "integrity": "sha512-XwoiiCV3Q9PBV1eFNAag1KnIqN/cNDoNi2B6BJUkGPJUEW3AgrOABV6cmyZ3yEKUEXMZ78JIfS9kUEmTtCAY0g==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.51-1.tgz", + "integrity": "sha512-MrzXNjYTUbtiPReJfIOC55o1NDbRTTBubpiNBLit1q07QL8Q/ozp1NoNZ2p8z1u962lDDztPEPXlvs9dsq40VQ==", "cpu": [ "x64" ], diff --git a/nodejs/package.json b/nodejs/package.json index 37d650a13..f9e05d29c 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -56,7 +56,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@github/copilot": "^1.0.49", + "@github/copilot": "^1.0.51-1", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, diff --git a/nodejs/samples/package-lock.json b/nodejs/samples/package-lock.json index 0e1ca6804..3678eea36 100644 --- a/nodejs/samples/package-lock.json +++ b/nodejs/samples/package-lock.json @@ -18,7 +18,7 @@ "version": "0.1.8", "license": "MIT", "dependencies": { - "@github/copilot": "^1.0.49", + "@github/copilot": "^1.0.51-1", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.6" }, diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index 8182d9ad0..1e42ef3e7 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -5,8 +5,30 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; -import type { EmbeddedBlobResourceContents, EmbeddedTextResourceContents, McpServerSource, McpServerStatus, ReasoningSummary, SessionMode, SkillSource } from "./session-events.js"; +import type { AbortReason, EmbeddedBlobResourceContents, EmbeddedTextResourceContents, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, ReasoningSummary, SessionEvent, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval } from "./session-events.js"; +/** + * Where the agent definition was loaded from + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "AgentInfoSource". + */ +/** @experimental */ +export type AgentInfoSource = "user" | "project" | "inherited" | "remote" | "plugin" | "builtin"; +/** + * The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "AuthInfo". + */ +export type AuthInfo = + | HMACAuthInfo + | EnvAuthInfo + | TokenAuthInfo + | CopilotApiTokenAuthInfo + | UserAuthInfo + | GhCliAuthInfo + | ApiKeyAuthInfo; /** * Authentication type * @@ -29,7 +51,7 @@ export type SlashCommandKind = "builtin" | "skill" | "client"; */ export type SlashCommandInputCompletion = "directory"; /** - * Result of the queued command execution + * Result of the queued command execution. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "QueuedCommandResult". @@ -57,6 +79,30 @@ export type ContentFilterMode = "none" | "markdown" | "hidden_characters"; * via the `definition` "DiscoveredMcpServerType". */ export type DiscoveredMcpServerType = "stdio" | "http" | "sse" | "memory"; +/** + * Either '*' to receive all event types, or a non-empty list of event types to receive + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventLogTypes". + */ +/** @experimental */ +export type EventLogTypes = "*" | [string, ...string[]]; +/** + * Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventsAgentScope". + */ +/** @experimental */ +export type EventsAgentScope = "primary" | "all"; +/** + * Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventsCursorStatus". + */ +/** @experimental */ +export type EventsCursorStatus = "ok" | "expired"; /** * Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) * @@ -127,20 +173,39 @@ export type FilterMapping = [k: string]: ContentFilterMode; } | ContentFilterMode; +/** + * Source for direct repo installs (when marketplace is empty) + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "InstalledPluginSource". + */ +/** @experimental */ +export type InstalledPluginSource = + | string + | InstalledPluginSourceGithub + | InstalledPluginSourceUrl + | InstalledPluginSourceLocal; /** * Category of instruction source — used for merge logic * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "InstructionsSourcesType". */ -export type InstructionsSourcesType = "home" | "repo" | "model" | "vscode" | "nested-agents" | "child-instructions"; +export type InstructionsSourcesType = + | "home" + | "repo" + | "model" + | "vscode" + | "nested-agents" + | "child-instructions" + | "plugin"; /** * Where this source lives — used for UI grouping * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "InstructionsSourcesLocation". */ -export type InstructionsSourcesLocation = "user" | "repository" | "working-directory"; +export type InstructionsSourcesLocation = "user" | "repository" | "working-directory" | "plugin"; /** * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info". * @@ -169,6 +234,91 @@ export type McpServerConfigHttpType = "http" | "sse"; * via the `definition` "McpServerConfigHttpOauthGrantType". */ export type McpServerConfigHttpOauthGrantType = "authorization_code" | "client_credentials"; +/** + * Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpSamplingExecutionAction". + */ +/** @experimental */ +export type McpSamplingExecutionAction = "success" | "failure" | "cancelled"; +/** + * How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpSetEnvValueModeDetails". + */ +/** @experimental */ +export type McpSetEnvValueModeDetails = "direct" | "indirect"; +/** + * Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionContextInfo". + */ +/** @experimental */ +export type SessionContextInfo = { + /** + * The model used for token counting + */ + modelName: string; + /** + * Tokens consumed by the system prompt + */ + systemTokens: number; + /** + * Tokens consumed by user/assistant/tool messages + */ + conversationTokens: number; + /** + * Tokens consumed by tool definitions sent to the model (excludes deferred tools) + */ + toolDefinitionsTokens: number; + /** + * Sum of system, conversation and tool-definition tokens + */ + totalTokens: number; + /** + * Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified) + */ + promptTokenLimit: number; + /** + * Token count at which background compaction starts (configurable percentage of promptTokenLimit) + */ + compactionThreshold: number; + /** + * Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. + */ + limit: number; + /** + * Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%) + */ + bufferTokens: number; +} | null; +/** + * Hosting platform type of the repository + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionWorkingDirectoryContextHostType". + */ +/** @experimental */ +export type SessionWorkingDirectoryContextHostType = "github" | "ado"; +/** + * The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataSnapshotCurrentMode". + */ +/** @experimental */ +export type MetadataSnapshotCurrentMode = "interactive" | "plan" | "autopilot"; +/** + * Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` invocation. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataSnapshotRemoteMetadataTaskType". + */ +/** @experimental */ +export type MetadataSnapshotRemoteMetadataTaskType = "cca" | "cli"; /** * Current policy state for this model * @@ -191,7 +341,15 @@ export type ModelPickerCategory = "lightweight" | "versatile" | "powerful"; */ export type ModelPickerPriceCategory = "low" | "medium" | "high" | "very_high"; /** - * Decision to apply to a pending permission request. + * How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "OptionsUpdateEnvValueMode". + */ +/** @experimental */ +export type OptionsUpdateEnvValueMode = "direct" | "indirect"; +/** + * The client's response to the pending permission prompt * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "PermissionDecision". @@ -202,9 +360,18 @@ export type PermissionDecision = | PermissionDecisionApproveForLocation | PermissionDecisionApprovePermanently | PermissionDecisionReject - | PermissionDecisionUserNotAvailable; + | PermissionDecisionUserNotAvailable + | PermissionDecisionApproved + | PermissionDecisionApprovedForSession + | PermissionDecisionApprovedForLocation + | PermissionDecisionCancelled + | PermissionDecisionDeniedByRules + | PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser + | PermissionDecisionDeniedInteractivelyByUser + | PermissionDecisionDeniedByContentExclusionPolicy + | PermissionDecisionDeniedByPermissionRequestHook; /** - * The approval to add as a session-scoped rule + * Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "PermissionDecisionApproveForSessionApproval". @@ -220,7 +387,7 @@ export type PermissionDecisionApproveForSessionApproval = | PermissionDecisionApproveForSessionApprovalExtensionManagement | PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess; /** - * The approval to persist for this location + * Approval to persist for this location * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "PermissionDecisionApproveForLocationApproval". @@ -235,6 +402,35 @@ export type PermissionDecisionApproveForLocationApproval = | PermissionDecisionApproveForLocationApprovalCustomTool | PermissionDecisionApproveForLocationApprovalExtensionManagement | PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess; +/** + * Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsConfigureAdditionalContentExclusionPolicyScope". + */ +export type PermissionsConfigureAdditionalContentExclusionPolicyScope = "repo" | "all"; +/** + * Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsModifyRulesScope". + */ +export type PermissionsModifyRulesScope = "session" | "location"; +/** + * Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsSetApproveAllSource". + */ +export type PermissionsSetApproveAllSource = "cli_flag" | "slash_command" | "autopilot_confirmation" | "rpc"; +/** + * Whether this item is a queued user message or a queued slash command / model change + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "QueuePendingItemsKind". + */ +/** @experimental */ +export type QueuePendingItemsKind = "message" | "command"; /** * Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. * @@ -243,6 +439,47 @@ export type PermissionDecisionApproveForLocationApproval = */ /** @experimental */ export type RemoteSessionMode = "off" | "export" | "on"; +/** + * The UI mode the agent was in when this message was sent. Defaults to the session's current mode. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAgentMode". + */ +export type SendAgentMode = "interactive" | "plan" | "autopilot" | "shell"; +/** + * A user message attachment — a file, directory, code selection, blob, or GitHub reference + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachment". + */ +export type SendAttachment = + | SendAttachmentFile + | SendAttachmentDirectory + | SendAttachmentSelection + | SendAttachmentGithubReference + | SendAttachmentBlob; +/** + * Type of GitHub reference + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentGithubReferenceType". + */ +export type SendAttachmentGithubReferenceType = "issue" | "pr" | "discussion"; +/** + * How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendMode". + */ +export type SendMode = "enqueue" | "immediate"; +/** + * Repository host type + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionContextHostType". + */ +/** @experimental */ +export type SessionContextHostType = "github" | "ado"; /** * Error classification * @@ -271,6 +508,63 @@ export type SessionFsSetProviderConventions = "windows" | "posix"; * via the `definition` "SessionFsSqliteQueryType". */ export type SessionFsSqliteQueryType = "exec" | "query" | "run"; +/** + * Source descriptor for direct repo installs (when marketplace is empty) + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionInstalledPluginSource". + */ +/** @experimental */ +export type SessionInstalledPluginSource = + | string + | SessionInstalledPluginSourceGithub + | SessionInstalledPluginSourceUrl + | SessionInstalledPluginSourceLocal; +/** + * Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspaceSummary". + */ +/** @experimental */ +export type WorkspaceSummary = { + /** + * Workspace identifier (1:1 with sessionId) + */ + id: string; + /** + * Current working directory at session start + */ + cwd?: string; + /** + * Resolved git root for cwd, if any + */ + git_root?: string; + /** + * Repository identifier in 'owner/repo' or 'org/project/repo' format, if any + */ + repository?: string; + /** + * Repository host type, if known + */ + host_type?: "github" | "ado"; + /** + * Branch checked out at session start, if any + */ + branch?: string; + /** + * Display name for the session, if set + */ + name?: string; + /** + * ISO 8601 timestamp when the workspace was created + */ + created_at?: string; + /** + * ISO 8601 timestamp when the workspace was last updated + */ + updated_at?: string; +} | null; /** * Signal to send (default: SIGTERM) * @@ -304,6 +598,51 @@ export type TaskStatus = "running" | "idle" | "completed" | "failed" | "cancelle */ /** @experimental */ export type TaskExecutionMode = "sync" | "background"; +/** + * Schema for the `TaskAgentProgress` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TaskAgentProgress". + */ +/** @experimental */ +export type TaskAgentProgress = + | { + /** + * Progress kind + */ + type: "agent"; + /** + * Recent tool execution events converted to display lines + */ + recentActivity: { + /** + * Display message, e.g., "▸ bash", "✓ edit src/foo.ts" + */ + message: string; + /** + * ISO 8601 timestamp when this event occurred + */ + timestamp: string; + }[]; + /** + * The most recent intent reported by the agent + */ + latestIntent?: string; + } + | { + /** + * Progress kind + */ + type: "shell"; + /** + * Recent stdout/stderr lines from the running shell command + */ + recentOutput: string; + /** + * Process ID when available + */ + pid?: number; + }; /** * Schema for the `TaskInfo` type. * @@ -320,6 +659,29 @@ export type TaskInfo = TaskAgentInfo | TaskShellInfo; */ /** @experimental */ export type TaskShellInfoAttachmentMode = "attached" | "detached"; +/** + * Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TaskProgress". + */ +/** @experimental */ +export type TaskProgress = TaskAgentProgress | TaskShellProgress; +/** + * Schema for the `TaskShellProgress` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TaskShellProgress". + */ +/** @experimental */ +export type TaskShellProgress = null; +/** + * User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIAutoModeSwitchResponse". + */ +export type UIAutoModeSwitchResponse = "yes" | "yes_always" | "no"; /** * Schema for the `UIElicitationFieldValue` type. * @@ -362,6 +724,39 @@ export type UIElicitationSchemaPropertyNumberType = "number" | "integer"; * via the `definition` "UIElicitationResponseAction". */ export type UIElicitationResponseAction = "accept" | "decline" | "cancel"; +/** + * The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIExitPlanModeAction". + */ +export type UIExitPlanModeAction = "exit_only" | "interactive" | "autopilot" | "autopilot_fleet"; + +/** + * Parameters for aborting the current turn + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "AbortRequest". + */ +export interface AbortRequest { + reason?: AbortReason; +} +/** + * Result of aborting the current turn + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "AbortResult". + */ +export interface AbortResult { + /** + * Whether the abort completed successfully + */ + success: boolean; + /** + * Error message if the abort failed + */ + error?: string; +} export interface AccountGetQuotaRequest { /** @@ -460,6 +855,33 @@ export interface AgentInfo { * Absolute local file path of the agent definition. Only set for file-based agents loaded from disk; remote agents do not have a path. */ path?: string; + /** + * Stable identifier for selection. For most agents this is the same as `name`; for plugin/builtin agents it may differ. Always populated; defaults to `name` when no distinct id was assigned. + */ + id: string; + source?: AgentInfoSource; + /** + * Whether the agent can be selected directly by the user. Agents marked `false` are subagent-only. + */ + userInvocable?: boolean; + /** + * Allowed tool names for this agent. Empty array means none; omitted means inherit defaults. + */ + tools?: string[]; + /** + * Preferred model id for this agent. When omitted, inherits the outer agent's model. + */ + model?: string; + /** + * MCP server configurations attached to this agent, keyed by server name. Server config shape mirrors the MCP `mcpServers` schema. + */ + mcpServers?: { + [k: string]: unknown; + }; + /** + * Skill names preloaded into this agent's context. Omitted means none. + */ + skills?: string[]; } /** * Custom agents available to the session. @@ -511,54 +933,379 @@ export interface AgentSelectResult { agent: AgentInfo; } /** - * Slash commands available in the session, after applying any include/exclude filters. + * Schema for the `ApiKeyAuthInfo` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "CommandList". + * via the `definition` "ApiKeyAuthInfo". */ -export interface CommandList { +export interface ApiKeyAuthInfo { /** - * Commands available in this session + * API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style). */ - commands: SlashCommandInfo[]; + type: "api-key"; + /** + * The API key. Treat as a secret. + */ + apiKey: string; + /** + * Authentication host. + */ + host: string; + copilotUser?: CopilotUserResponse; } /** - * Schema for the `SlashCommandInfo` type. + * Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SlashCommandInfo". + * via the `definition` "CopilotUserResponse". */ -export interface SlashCommandInfo { - /** - * Canonical command name without a leading slash - */ - name: string; - /** - * Canonical aliases without leading slashes - */ - aliases?: string[]; - /** - * Human-readable command description - */ - description: string; - kind: SlashCommandKind; - input?: SlashCommandInput; - /** - * Whether the command may run while an agent turn is active - */ - allowDuringAgentExecution: boolean; - /** - * Whether the command is experimental - */ - experimental?: boolean; +export interface CopilotUserResponse { + login?: string; + access_type_sku?: string; + analytics_tracking_id?: string; + assigned_date?: + | ( + | { + [k: string]: unknown; + } + | string + ) + | null; + can_signup_for_limited?: boolean; + chat_enabled?: boolean; + copilot_plan?: string; + copilotignore_enabled?: boolean; + endpoints?: CopilotUserResponseEndpoints; + organization_login_list?: string[]; + organization_list?: + | ( + | { + [k: string]: unknown; + } + | ({ + login?: + | ( + | { + [k: string]: unknown; + } + | string + ) + | null; + name?: + | ( + | { + [k: string]: unknown; + } + | string + ) + | null; + } | null)[] + ) + | null; + codex_agent_enabled?: boolean; + is_mcp_enabled?: + | ( + | { + [k: string]: unknown; + } + | boolean + ) + | null; + quota_reset_date?: string; + quota_snapshots?: CopilotUserResponseQuotaSnapshots; + restricted_telemetry?: boolean; + token_based_billing?: boolean; + quota_reset_date_utc?: string; + limited_user_quotas?: { + [k: string]: number; + }; + limited_user_reset_date?: string; + monthly_quotas?: { + [k: string]: number; + }; + cloud_session_storage_enabled?: boolean; + cli_remote_control_enabled?: boolean; } /** - * Optional unstructured input hint + * Schema for the `CopilotUserResponseEndpoints` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SlashCommandInput". + * via the `definition` "CopilotUserResponseEndpoints". */ -export interface SlashCommandInput { +export interface CopilotUserResponseEndpoints { + api?: string; + "origin-tracker"?: string; + proxy?: string; + telemetry?: string; +} +/** + * Schema for the `CopilotUserResponseQuotaSnapshots` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CopilotUserResponseQuotaSnapshots". + */ +export interface CopilotUserResponseQuotaSnapshots { + chat?: CopilotUserResponseQuotaSnapshotsChat; + completions?: CopilotUserResponseQuotaSnapshotsCompletions; + premium_interactions?: CopilotUserResponseQuotaSnapshotsPremiumInteractions; + [k: string]: { + entitlement?: number; + overage_count?: number; + overage_permitted?: boolean; + percent_remaining?: number; + quota_id?: string; + quota_remaining?: number; + remaining?: number; + unlimited?: boolean; + timestamp_utc?: string; + has_quota?: boolean; + quota_reset_at?: number; + token_based_billing?: boolean; + } | null; +} +/** + * Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CopilotUserResponseQuotaSnapshotsChat". + */ +export interface CopilotUserResponseQuotaSnapshotsChat { + entitlement?: number; + overage_count?: number; + overage_permitted?: boolean; + percent_remaining?: number; + quota_id?: string; + quota_remaining?: number; + remaining?: number; + unlimited?: boolean; + timestamp_utc?: string; + has_quota?: boolean; + quota_reset_at?: number; + token_based_billing?: boolean; +} +/** + * Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CopilotUserResponseQuotaSnapshotsCompletions". + */ +export interface CopilotUserResponseQuotaSnapshotsCompletions { + entitlement?: number; + overage_count?: number; + overage_permitted?: boolean; + percent_remaining?: number; + quota_id?: string; + quota_remaining?: number; + remaining?: number; + unlimited?: boolean; + timestamp_utc?: string; + has_quota?: boolean; + quota_reset_at?: number; + token_based_billing?: boolean; +} +/** + * Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CopilotUserResponseQuotaSnapshotsPremiumInteractions". + */ +export interface CopilotUserResponseQuotaSnapshotsPremiumInteractions { + entitlement?: number; + overage_count?: number; + overage_permitted?: boolean; + percent_remaining?: number; + quota_id?: string; + quota_remaining?: number; + remaining?: number; + unlimited?: boolean; + timestamp_utc?: string; + has_quota?: boolean; + quota_reset_at?: number; + token_based_billing?: boolean; +} +/** + * Schema for the `HMACAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "HMACAuthInfo". + */ +export interface HMACAuthInfo { + /** + * HMAC-based authentication used by GitHub-internal services. + */ + type: "hmac"; + /** + * Authentication host. HMAC auth always targets the public GitHub host. + */ + host: "https://github.com"; + /** + * HMAC secret used to sign requests. + */ + hmac: string; + copilotUser?: CopilotUserResponse; +} +/** + * Schema for the `EnvAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EnvAuthInfo". + */ +export interface EnvAuthInfo { + /** + * Personal access token (PAT) or server-to-server token sourced from an environment variable. + */ + type: "env"; + /** + * Authentication host (e.g. https://github.com or a GHES host). + */ + host: string; + /** + * User login associated with the token. Undefined for server-to-server tokens (those starting with `ghs_`). + */ + login?: string; + /** + * The token value itself. Treat as a secret. + */ + token: string; + /** + * Name of the environment variable the token was sourced from. + */ + envVar: string; + copilotUser?: CopilotUserResponse; +} +/** + * Schema for the `TokenAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TokenAuthInfo". + */ +export interface TokenAuthInfo { + /** + * SDK-side token authentication; the host configured the token directly via the SDK. + */ + type: "token"; + /** + * Authentication host. + */ + host: string; + /** + * The token value itself. Treat as a secret. + */ + token: string; + copilotUser?: CopilotUserResponse; +} +/** + * Schema for the `CopilotApiTokenAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CopilotApiTokenAuthInfo". + */ +export interface CopilotApiTokenAuthInfo { + /** + * Direct Copilot API authentication via the `GITHUB_COPILOT_API_TOKEN` + `COPILOT_API_URL` environment-variable pair. The token itself is read from the environment by the runtime, not carried in this struct. + */ + type: "copilot-api-token"; + /** + * Authentication host (always the public GitHub host). + */ + host: "https://github.com"; + copilotUser?: CopilotUserResponse; +} +/** + * Schema for the `UserAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UserAuthInfo". + */ +export interface UserAuthInfo { + /** + * OAuth user authentication. The token itself is held in the runtime's secret token store (keyed by host+login) and is NOT carried in this struct. + */ + type: "user"; + /** + * Authentication host. + */ + host: string; + /** + * OAuth user login. + */ + login: string; + copilotUser?: CopilotUserResponse; +} +/** + * Schema for the `GhCliAuthInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "GhCliAuthInfo". + */ +export interface GhCliAuthInfo { + /** + * Authentication via the `gh` CLI's saved credentials. + */ + type: "gh-cli"; + /** + * Authentication host. + */ + host: string; + /** + * User login as reported by `gh auth status`. + */ + login: string; + /** + * The token returned by `gh auth token`. Treat as a secret. + */ + token: string; + copilotUser?: CopilotUserResponse; +} +/** + * Slash commands available in the session, after applying any include/exclude filters. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "CommandList". + */ +export interface CommandList { + /** + * Commands available in this session + */ + commands: SlashCommandInfo[]; +} +/** + * Schema for the `SlashCommandInfo` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SlashCommandInfo". + */ +export interface SlashCommandInfo { + /** + * Canonical command name without a leading slash + */ + name: string; + /** + * Canonical aliases without leading slashes + */ + aliases?: string[]; + /** + * Human-readable command description + */ + description: string; + kind: SlashCommandKind; + input?: SlashCommandInput; + /** + * Whether the command may run while an agent turn is active + */ + allowDuringAgentExecution: boolean; + /** + * Whether the command is experimental + */ + experimental?: boolean; +} +/** + * Optional unstructured input hint + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SlashCommandInput". + */ +export interface SlashCommandInput { /** * Hint to display when command input has not been provided */ @@ -638,14 +1385,14 @@ export interface CommandsListRequest { includeClientCommands?: boolean; } /** - * Queued command request ID and the result indicating whether the client handled it. + * Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "CommandsRespondToQueuedCommandRequest". */ export interface CommandsRespondToQueuedCommandRequest { /** - * Request ID from the queued command event + * Request ID from the `command.queued` event the host is responding to. */ requestId: string; result: QueuedCommandResult; @@ -658,11 +1405,11 @@ export interface CommandsRespondToQueuedCommandRequest { */ export interface QueuedCommandHandled { /** - * The command was handled + * The host actually executed the queued command. */ handled: true; /** - * If true, stop processing remaining queued items + * When true, the runtime will not process subsequent queued commands until a new request comes in. */ stopProcessingQueue?: boolean; } @@ -674,19 +1421,19 @@ export interface QueuedCommandHandled { */ export interface QueuedCommandNotHandled { /** - * The command was not handled + * The host did not execute the queued command. Unblocks the queue without claiming the command was processed (e.g. when the handler threw before completing). */ handled: false; } /** - * Indicates whether the queued-command response was accepted by the session. + * Indicates whether the queued-command response was matched to a pending request. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "CommandsRespondToQueuedCommandResult". */ export interface CommandsRespondToQueuedCommandResult { /** - * Whether the response was accepted (false if the requestId was not found or already resolved) + * Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. */ success: boolean; } @@ -806,7 +1553,7 @@ export interface ConnectResult { version: string; } /** - * The currently selected model for the session. + * The currently selected model and reasoning effort for the session. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "CurrentModel". @@ -816,6 +1563,10 @@ export interface CurrentModel { * Currently active model identifier */ modelId?: string; + /** + * Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. + */ + reasoningEffort?: string; } /** * Schema for the `DiscoveredMcpServer` type. @@ -835,6 +1586,129 @@ export interface DiscoveredMcpServer { */ enabled: boolean; } +/** + * Slash-prefixed command string to enqueue for FIFO processing. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EnqueueCommandParams". + */ +export interface EnqueueCommandParams { + /** + * Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. + */ + command: string; +} +/** + * Indicates whether the command was accepted into the local execution queue. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EnqueueCommandResult". + */ +export interface EnqueueCommandResult { + /** + * True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). + */ + queued: boolean; +} +/** + * Cursor, batch size, and optional long-poll/filter parameters for reading session events. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventLogReadRequest". + */ +/** @experimental */ +export interface EventLogReadRequest { + /** + * Opaque cursor returned by a previous read. Omit on the first call to start from the beginning of the session's persisted history. + */ + cursor?: string; + /** + * Maximum number of events to return in this batch (1–1000, default 200). + */ + max?: number; + /** + * Milliseconds to wait for new events when the cursor is at the tail of history. 0 (default) returns immediately even if no events are available. Capped at 30000ms. Ephemeral events that arrive during the wait are delivered in this batch but are NOT replayable on a subsequent read (use a non-zero waitMs in your next call to capture future ephemerals as they happen). + */ + waitMs?: number; + types?: EventLogTypes; + agentScope?: EventsAgentScope; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventLogReleaseInterestResult". + */ +/** @experimental */ +export interface EventLogReleaseInterestResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventLogTailResult". + */ +/** @experimental */ +export interface EventLogTailResult { + /** + * Opaque cursor pointing at the current tail of the session's persisted-events history. Pass back to `read` to receive only events that arrive AFTER this snapshot. When the session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent to omitting the cursor on a first read). + */ + cursor: string; +} +/** + * Batch of session events returned by a read, with cursor and continuation metadata. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "EventsReadResult". + */ +/** @experimental */ +export interface EventsReadResult { + /** + * Events are delivered in two batches per read: persisted events first (in append order), then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral events do not interleave within a single read. + */ + events: SessionEvent[]; + /** + * Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue from where this read left off. Always present, even when no events were returned. + */ + cursor: string; + /** + * True when the read returned `max` events and more events are available immediately. When false, the next read with a non-zero `waitMs` will block until a new event arrives or the wait expires. + */ + hasMore: boolean; + cursorStatus: EventsCursorStatus; +} +/** + * Slash command name and argument string to execute synchronously. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ExecuteCommandParams". + */ +export interface ExecuteCommandParams { + /** + * Name of the slash command to invoke (without the leading '/'). + */ + commandName: string; + /** + * Argument string to pass to the command (empty string if none). + */ + args: string; +} +/** + * Error message produced while executing the command, if any. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ExecuteCommandResult". + */ +export interface ExecuteCommandResult { + /** + * Error message produced while executing the command, if any. Omitted when the handler succeeded. + */ + error?: string; +} /** * Schema for the `Extension` type. * @@ -1166,6 +2040,32 @@ export interface HandlePendingToolCallResult { */ success: boolean; } +/** + * Indicates whether an in-progress manual compaction was aborted. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "HistoryAbortManualCompactionResult". + */ +/** @experimental */ +export interface HistoryAbortManualCompactionResult { + /** + * Whether an in-progress manual compaction was aborted. False when no manual compaction was running, when its abort controller was already aborted, or when the session is remote. + */ + aborted: boolean; +} +/** + * Indicates whether an in-progress background compaction was cancelled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "HistoryCancelBackgroundCompactionResult". + */ +/** @experimental */ +export interface HistoryCancelBackgroundCompactionResult { + /** + * Whether an in-progress background compaction was cancelled. False when no compaction was running, when the session is remote, or when the underlying processor was unavailable. + */ + cancelled: boolean; +} /** * Post-compaction context window usage breakdown * @@ -1200,7 +2100,7 @@ export interface HistoryCompactContextWindow { toolDefinitionsTokens?: number; } /** - * Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. + * Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "HistoryCompactResult". @@ -1219,8 +2119,25 @@ export interface HistoryCompactResult { * Number of messages removed during compaction */ messagesRemoved: number; + /** + * Summary text produced by compaction. Omitted when compaction did not produce a summary (e.g. failure path). + */ + summaryContent?: string; contextWindow?: HistoryCompactContextWindow; } +/** + * Markdown summary of the conversation context (empty when not available). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "HistorySummarizeForHandoffResult". + */ +/** @experimental */ +export interface HistorySummarizeForHandoffResult { + /** + * Markdown summary of the conversation context produced by an LLM. Empty string when there are no messages or when the session does not support local summarization. + */ + summary: string; +} /** * Identifier of the event to truncate to; this event and all later events are removed. * @@ -1248,18 +2165,98 @@ export interface HistoryTruncateResult { eventsRemoved: number; } /** - * Instruction sources loaded for the session, in merge order. + * Schema for the `InstalledPlugin` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "InstructionsGetSourcesResult". + * via the `definition` "InstalledPlugin". */ -export interface InstructionsGetSourcesResult { +/** @experimental */ +export interface InstalledPlugin { /** - * Instruction sources for the session + * Plugin name */ - sources: InstructionsSources[]; -} -/** + name: string; + /** + * Marketplace the plugin came from (empty string for direct repo installs) + */ + marketplace: string; + /** + * Version installed (if available) + */ + version?: string; + /** + * Installation timestamp + */ + installed_at: string; + /** + * Whether the plugin is currently enabled + */ + enabled: boolean; + /** + * Path where the plugin is cached locally + */ + cache_path?: string; + source?: InstalledPluginSource; +} +/** + * Schema for the `InstalledPluginSourceGithub` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "InstalledPluginSourceGithub". + */ +/** @experimental */ +export interface InstalledPluginSourceGithub { + /** + * Constant value. Always "github". + */ + source: "github"; + repo: string; + ref?: string; + path?: string; +} +/** + * Schema for the `InstalledPluginSourceUrl` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "InstalledPluginSourceUrl". + */ +/** @experimental */ +export interface InstalledPluginSourceUrl { + /** + * Constant value. Always "url". + */ + source: "url"; + url: string; + ref?: string; + path?: string; +} +/** + * Schema for the `InstalledPluginSourceLocal` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "InstalledPluginSourceLocal". + */ +/** @experimental */ +export interface InstalledPluginSourceLocal { + /** + * Constant value. Always "local". + */ + source: "local"; + path: string; +} +/** + * Instruction sources loaded for the session, in merge order. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "InstructionsGetSourcesResult". + */ +export interface InstructionsGetSourcesResult { + /** + * Instruction sources for the session + */ + sources: InstructionsSources[]; +} +/** * Schema for the `InstructionsSources` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema @@ -1285,16 +2282,20 @@ export interface InstructionsSources { type: InstructionsSourcesType; location: InstructionsSourcesLocation; /** - * Glob pattern from frontmatter — when set, this instruction applies only to matching files + * Glob pattern(s) from frontmatter — when set, this instruction applies only to matching files */ - applyTo?: string; + applyTo?: string[]; /** * Short description (body after frontmatter) for use in instruction tables */ description?: string; + /** + * When true, this source starts disabled and must be toggled on by the user + */ + defaultDisabled?: boolean; } /** - * Message text, optional severity level, persistence flag, and optional follow-up URL. + * Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "LogRequest". @@ -1305,6 +2306,10 @@ export interface LogRequest { */ message: string; level?: SessionLogLevel; + /** + * Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". + */ + type?: string; /** * When true, the message is transient and not persisted to the session event log on disk */ @@ -1313,6 +2318,10 @@ export interface LogRequest { * Optional URL the user can open in their browser for more details */ url?: string; + /** + * Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. + */ + tip?: string; } /** * Identifier of the session event that was emitted for the log message. @@ -1326,6 +2335,53 @@ export interface LogResult { */ eventId: string; } +/** + * Parameters for (re)loading the merged LSP configuration set. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "LspInitializeRequest". + */ +/** @experimental */ +export interface LspInitializeRequest { + /** + * Working directory used to load project-level LSP configs. Defaults to the session working directory when omitted. + */ + workingDirectory?: string; + /** + * Git root used as the boundary when traversing for project-level LSP configs (supports monorepos). + */ + gitRoot?: string; + /** + * Force re-initialization even when LSP configs were already loaded for the working directory. + */ + force?: boolean; +} +/** + * The requestId previously passed to executeSampling that should be cancelled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpCancelSamplingExecutionParams". + */ +/** @experimental */ +export interface McpCancelSamplingExecutionParams { + /** + * The requestId previously passed to executeSampling that should be cancelled + */ + requestId: string; +} +/** + * Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpCancelSamplingExecutionResult". + */ +/** @experimental */ +export interface McpCancelSamplingExecutionResult { + /** + * True if an in-flight execution with the given requestId was found and signalled to cancel. False when no such execution is in flight (already completed, never started, or cancelled by another caller). + */ + cancelled: boolean; +} /** * MCP server name and configuration to add to user configuration. * @@ -1545,6 +2601,48 @@ export interface McpEnableRequest { */ serverName: string; } +/** + * Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpExecuteSamplingParams". + */ +/** @experimental */ +export interface McpExecuteSamplingParams { + /** + * Caller-provided unique identifier for this sampling execution. Use this same ID with cancelSamplingExecution to cancel the in-flight call. Must be unique within the session for the lifetime of the call. + */ + requestId: string; + /** + * Name of the MCP server that initiated the sampling request + */ + serverName: string; + /** + * The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate the inference with the originating MCP request for telemetry; this is distinct from `requestId` (which is the schema-level cancellation handle). + */ + mcpRequestId: string | number; + request: McpExecuteSamplingRequest; +} +/** + * Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpExecuteSamplingRequest". + */ +/** @experimental */ +export interface McpExecuteSamplingRequest { + [k: string]: unknown; +} +/** + * MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpExecuteSamplingResult". + */ +/** @experimental */ +export interface McpExecuteSamplingResult { + [k: string]: unknown; +} /** * Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. * @@ -1583,6 +2681,34 @@ export interface McpOauthLoginResult { */ authorizationUrl?: string; } +/** + * Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpRemoveGitHubResult". + */ +/** @experimental */ +export interface McpRemoveGitHubResult { + /** + * True when the auto-managed `github` MCP server was removed; false when no removal happened (e.g. user has explicitly configured a `github` server, or the server was not registered). + */ + removed: boolean; +} +/** + * Outcome of an MCP sampling execution: success result, failure error, or cancellation. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpSamplingExecutionResult". + */ +/** @experimental */ +export interface McpSamplingExecutionResult { + action: McpSamplingExecutionAction; + result?: McpExecuteSamplingResult; + /** + * Error description, present when action='failure'. + */ + error?: string; +} /** * Schema for the `McpServer` type. * @@ -1616,138 +2742,361 @@ export interface McpServerList { servers: McpServer[]; } /** - * Schema for the `Model` type. + * Mode controlling how MCP server env values are resolved (`direct` or `indirect`). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "Model". + * via the `definition` "McpSetEnvValueModeParams". */ -export interface Model { - /** - * Model identifier (e.g., "claude-sonnet-4.5") - */ - id: string; +/** @experimental */ +export interface McpSetEnvValueModeParams { + mode: McpSetEnvValueModeDetails; +} +/** + * Env-value mode recorded on the session after the update. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "McpSetEnvValueModeResult". + */ +/** @experimental */ +export interface McpSetEnvValueModeResult { + mode: McpSetEnvValueModeDetails; +} +/** + * Model identifier and token limits used to compute the context-info breakdown. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataContextInfoRequest". + */ +/** @experimental */ +export interface MetadataContextInfoRequest { /** - * Display name + * Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. */ - name: string; - capabilities: ModelCapabilities; - policy?: ModelPolicy; - billing?: ModelBilling; + promptTokenLimit: number; /** - * Supported reasoning effort levels (only present if model supports reasoning effort) + * Maximum output tokens allowed by the target model. Pass 0 if unknown. */ - supportedReasoningEfforts?: string[]; + outputTokenLimit: number; /** - * Default reasoning effort level (only present if model supports reasoning effort) + * Model identifier used for tokenization. Omit to use the session default. Used both for token counting and to compute display values. */ - defaultReasoningEffort?: string; - modelPickerCategory?: ModelPickerCategory; - modelPickerPriceCategory?: ModelPickerPriceCategory; + selectedModel?: string; } /** - * Model capabilities and limits + * Token breakdown for the session's current context window, or null if uninitialized. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelCapabilities". + * via the `definition` "MetadataContextInfoResult". */ -export interface ModelCapabilities { - supports?: ModelCapabilitiesSupports; - limits?: ModelCapabilitiesLimits; +/** @experimental */ +export interface MetadataContextInfoResult { + /** + * Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). + */ + contextInfo?: SessionContextInfo | null; } /** - * Feature flags indicating what the model supports + * Indicates whether the local session is currently processing a turn or background continuation. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelCapabilitiesSupports". + * via the `definition` "MetadataIsProcessingResult". */ -export interface ModelCapabilitiesSupports { +/** @experimental */ +export interface MetadataIsProcessingResult { /** - * Whether this model supports vision/image input + * Whether the session is currently processing user/agent messages. False for non-local sessions (which don't run a local agentic loop). Reflects an in-flight turn or background continuation. */ - vision?: boolean; + processing: boolean; +} +/** + * Model identifier to use when re-tokenizing the session's existing messages. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataRecomputeContextTokensRequest". + */ +/** @experimental */ +export interface MetadataRecomputeContextTokensRequest { /** - * Whether this model supports reasoning effort configuration + * Model identifier used for tokenization. The runtime token-counts both chat-context and system-context messages against this model. */ - reasoningEffort?: boolean; + modelId: string; } /** - * Token limits for prompts, outputs, and context window + * Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelCapabilitiesLimits". + * via the `definition` "MetadataRecomputeContextTokensResult". */ -export interface ModelCapabilitiesLimits { +/** @experimental */ +export interface MetadataRecomputeContextTokensResult { /** - * Maximum number of prompt/input tokens + * Sum of tokens across chat-context and system-context messages currently held by the session. */ - max_prompt_tokens?: number; + totalTokens: number; /** - * Maximum number of output/completion tokens + * Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). */ - max_output_tokens?: number; + messagesTokenCount: number; /** - * Maximum total context window size in tokens + * Tokens contributed by system/developer prompt snapshots. */ - max_context_window_tokens?: number; - vision?: ModelCapabilitiesLimitsVision; + systemTokenCount: number; } /** - * Vision-specific limits + * Updated working-directory/git context to record on the session. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelCapabilitiesLimitsVision". + * via the `definition` "MetadataRecordContextChangeRequest". */ -export interface ModelCapabilitiesLimitsVision { +/** @experimental */ +export interface MetadataRecordContextChangeRequest { + context: SessionWorkingDirectoryContext; +} +/** + * Updated working directory and git context. Emitted as the new payload of `session.context_changed`. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionWorkingDirectoryContext". + */ +/** @experimental */ +export interface SessionWorkingDirectoryContext { /** - * MIME types the model accepts + * Current working directory path */ - supported_media_types: string[]; + cwd: string; /** - * Maximum number of images per prompt + * Root directory of the git repository, resolved via git rev-parse */ - max_prompt_images: number; + gitRoot?: string; /** - * Maximum image size in bytes + * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) */ - max_prompt_image_size: number; + repository?: string; + hostType?: SessionWorkingDirectoryContextHostType; + /** + * Raw host string from the git remote URL (e.g. "github.com", "dev.azure.com") + */ + repositoryHost?: string; + /** + * Current git branch name + */ + branch?: string; + /** + * Head commit of the current git branch + */ + headCommit?: string; + /** + * Merge-base commit SHA (fork point from the remote default branch) + */ + baseCommit?: string; } /** - * Policy state (if applicable) + * Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelPolicy". + * via the `definition` "MetadataRecordContextChangeResult". */ -export interface ModelPolicy { - state: ModelPolicyState; +/** @experimental */ +export interface MetadataRecordContextChangeResult {} +/** + * Absolute path to set as the session's new working directory. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataSetWorkingDirectoryRequest". + */ +/** @experimental */ +export interface MetadataSetWorkingDirectoryRequest { /** - * Usage terms or conditions for this model + * Absolute path to set as the session's working directory. The runtime updates the session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) anchor to it. */ - terms?: string; + workingDirectory: string; } /** - * Billing information + * Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelBilling". + * via the `definition` "MetadataSetWorkingDirectoryResult". */ -export interface ModelBilling { +/** @experimental */ +export interface MetadataSetWorkingDirectoryResult { /** - * Billing cost multiplier relative to the base rate + * Working directory after the update */ - multiplier?: number; - tokenPrices?: ModelBillingTokenPrices; + workingDirectory: string; } /** - * Token-level pricing information for this model + * Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ModelBillingTokenPrices". + * via the `definition` "MetadataSnapshotRemoteMetadata". */ -export interface ModelBillingTokenPrices { +/** @experimental */ +export interface MetadataSnapshotRemoteMetadata { /** - * Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) + * The original resource identifier (task ID or PR node ID), preserved across event-replay reconstructions. Falls back to `sessionId` when absent. */ - inputPrice?: number; + resourceId?: string; + repository: MetadataSnapshotRemoteMetadataRepository; + /** + * The pull request number the remote session is associated with, if any. + */ + pullRequestNumber?: number; + taskType?: MetadataSnapshotRemoteMetadataTaskType; +} +/** + * The repository the remote session targets. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "MetadataSnapshotRemoteMetadataRepository". + */ +/** @experimental */ +export interface MetadataSnapshotRemoteMetadataRepository { + /** + * The GitHub owner (user or organization) of the target repository. + */ + owner: string; + /** + * The GitHub repository name (without owner). + */ + name: string; + /** + * The branch the remote session is operating on. + */ + branch: string; +} +/** + * Schema for the `Model` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "Model". + */ +export interface Model { + /** + * Model identifier (e.g., "claude-sonnet-4.5") + */ + id: string; + /** + * Display name + */ + name: string; + capabilities: ModelCapabilities; + policy?: ModelPolicy; + billing?: ModelBilling; + /** + * Supported reasoning effort levels (only present if model supports reasoning effort) + */ + supportedReasoningEfforts?: string[]; + /** + * Default reasoning effort level (only present if model supports reasoning effort) + */ + defaultReasoningEffort?: string; + modelPickerCategory?: ModelPickerCategory; + modelPickerPriceCategory?: ModelPickerPriceCategory; +} +/** + * Model capabilities and limits + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelCapabilities". + */ +export interface ModelCapabilities { + supports?: ModelCapabilitiesSupports; + limits?: ModelCapabilitiesLimits; +} +/** + * Feature flags indicating what the model supports + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelCapabilitiesSupports". + */ +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 + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelCapabilitiesLimits". + */ +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 + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelCapabilitiesLimitsVision". + */ +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; +} +/** + * Policy state (if applicable) + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelPolicy". + */ +export interface ModelPolicy { + state: ModelPolicyState; + /** + * Usage terms or conditions for this model + */ + terms?: string; +} +/** + * Billing information + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelBilling". + */ +export interface ModelBilling { + /** + * Billing cost multiplier relative to the base rate + */ + multiplier?: number; + tokenPrices?: ModelBillingTokenPrices; +} +/** + * Token-level pricing information for this model + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelBillingTokenPrices". + */ +export interface ModelBillingTokenPrices { + /** + * Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) + */ + inputPrice?: number; /** * Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) */ @@ -1840,6 +3189,30 @@ export interface ModelList { */ models: Model[]; } +/** + * Reasoning effort level to apply to the currently selected model. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelSetReasoningEffortRequest". + */ +export interface ModelSetReasoningEffortRequest { + /** + * Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. + */ + reasoningEffort: string; +} +/** + * Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ModelSetReasoningEffortResult". + */ +export interface ModelSetReasoningEffortResult { + /** + * Reasoning effort level recorded on the session after the update + */ + reasoningEffort: string; +} export interface ModelsListRequest { /** @@ -1898,6 +3271,30 @@ export interface NameGetResult { */ name: string | null; } +/** + * Auto-generated session summary to apply as the session's name when no user-set name exists. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "NameSetAutoRequest". + */ +export interface NameSetAutoRequest { + /** + * Auto-generated session summary. Empty/whitespace-only values are ignored; values are trimmed before persisting. + */ + summary: string; +} +/** + * Indicates whether the auto-generated summary was applied as the session's name. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "NameSetAutoResult". + */ +export interface NameSetAutoResult { + /** + * Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. + */ + applied: boolean; +} /** * New friendly name to apply to the session. * @@ -1910,6 +3307,31 @@ export interface NameSetRequest { */ name: string; } +/** + * Schema for the `PendingPermissionRequest` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PendingPermissionRequest". + */ +export interface PendingPermissionRequest { + /** + * Unique identifier for the pending permission request + */ + requestId: string; + request: PermissionPromptRequest; +} +/** + * List of pending permission requests reconstructed from event history. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PendingPermissionRequestList". + */ +export interface PendingPermissionRequestList { + /** + * Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. + */ + items: PendingPermissionRequest[]; +} /** * Schema for the `PermissionDecisionApproveOnce` type. * @@ -1918,7 +3340,7 @@ export interface NameSetRequest { */ export interface PermissionDecisionApproveOnce { /** - * The permission request was approved for this one instance + * Approve this single request only */ kind: "approve-once"; } @@ -1930,12 +3352,12 @@ export interface PermissionDecisionApproveOnce { */ export interface PermissionDecisionApproveForSession { /** - * Approved and remembered for the rest of the session + * Approve and remember for the rest of the session */ kind: "approve-for-session"; approval?: PermissionDecisionApproveForSessionApproval; /** - * The URL domain to approve for this session + * URL domain to approve for the rest of the session (URL prompts only) */ domain?: string; } @@ -2083,12 +3505,12 @@ export interface PermissionDecisionApproveForSessionApprovalExtensionPermissionA */ export interface PermissionDecisionApproveForLocation { /** - * Approved and persisted for this project location + * Approve and persist for this project location */ kind: "approve-for-location"; approval: PermissionDecisionApproveForLocationApproval; /** - * The location key (git root or cwd) to persist the approval to + * Location key (git root or cwd) to persist the approval to */ locationKey: string; } @@ -2236,11 +3658,11 @@ export interface PermissionDecisionApproveForLocationApprovalExtensionPermission */ export interface PermissionDecisionApprovePermanently { /** - * Approved and persisted across sessions + * Approve and persist across sessions (URL prompts only) */ kind: "approve-permanently"; /** - * The URL domain to approve permanently + * URL domain to approve permanently */ domain: string; } @@ -2252,11 +3674,11 @@ export interface PermissionDecisionApprovePermanently { */ export interface PermissionDecisionReject { /** - * Denied by the user during an interactive prompt + * Reject the request */ kind: "reject"; /** - * Optional feedback from the user explaining the denial + * Optional feedback explaining the rejection */ feedback?: string; } @@ -2268,738 +3690,2513 @@ export interface PermissionDecisionReject { */ export interface PermissionDecisionUserNotAvailable { /** - * Denied because user confirmation was unavailable + * No user is available to confirm the request */ kind: "user-not-available"; } /** - * Pending permission request ID and the decision to apply (approve/reject and scope). + * Schema for the `PermissionDecisionApproved` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionDecisionRequest". + * via the `definition` "PermissionDecisionApproved". */ -export interface PermissionDecisionRequest { +export interface PermissionDecisionApproved { /** - * Request ID of the pending permission request + * The permission request was approved */ - requestId: string; - result: PermissionDecision; + kind: "approved"; } /** - * Indicates whether the permission decision was applied; false when the request was already resolved. + * Schema for the `PermissionDecisionApprovedForSession` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionRequestResult". + * via the `definition` "PermissionDecisionApprovedForSession". */ -export interface PermissionRequestResult { +export interface PermissionDecisionApprovedForSession { /** - * Whether the permission request was handled successfully + * Approved and remembered for the rest of the session */ - success: boolean; + kind: "approved-for-session"; + approval: UserToolSessionApproval; } /** - * No parameters; clears all session-scoped tool permission approvals. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionsResetSessionApprovalsRequest". - */ -export interface PermissionsResetSessionApprovalsRequest {} -/** - * Indicates whether the operation succeeded. + * Schema for the `PermissionDecisionApprovedForLocation` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionsResetSessionApprovalsResult". + * via the `definition` "PermissionDecisionApprovedForLocation". */ -export interface PermissionsResetSessionApprovalsResult { +export interface PermissionDecisionApprovedForLocation { /** - * Whether the operation succeeded + * Approved and persisted for this project location */ - success: boolean; + kind: "approved-for-location"; + approval: UserToolSessionApproval; + /** + * The location key (git root or cwd) to persist the approval to + */ + locationKey: string; } /** - * Whether to auto-approve all tool permission requests for the rest of the session. + * Schema for the `PermissionDecisionCancelled` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionsSetApproveAllRequest". + * via the `definition` "PermissionDecisionCancelled". */ -export interface PermissionsSetApproveAllRequest { +export interface PermissionDecisionCancelled { /** - * Whether to auto-approve all tool permission requests + * The permission request was cancelled before a response was used */ - enabled: boolean; + kind: "cancelled"; + /** + * Optional explanation of why the request was cancelled + */ + reason?: string; } /** - * Indicates whether the operation succeeded. + * Schema for the `PermissionDecisionDeniedByRules` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PermissionsSetApproveAllResult". + * via the `definition` "PermissionDecisionDeniedByRules". */ -export interface PermissionsSetApproveAllResult { +export interface PermissionDecisionDeniedByRules { /** - * Whether the operation succeeded + * Denied because approval rules explicitly blocked it */ - success: boolean; + kind: "denied-by-rules"; + /** + * Rules that denied the request + */ + rules: PermissionRule[]; } /** - * Optional message to echo back to the caller. + * Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PingRequest". + * via the `definition` "PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser". */ -export interface PingRequest { +export interface PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser { /** - * Optional message to echo back + * Denied because no approval rule matched and user confirmation was unavailable */ - message?: string; + kind: "denied-no-approval-rule-and-could-not-request-from-user"; } /** - * Server liveness response, including the echoed message, current timestamp, and protocol version. + * Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PingResult". + * via the `definition` "PermissionDecisionDeniedInteractivelyByUser". */ -export interface PingResult { +export interface PermissionDecisionDeniedInteractivelyByUser { /** - * Echoed message (or default greeting) + * Denied by the user during an interactive prompt */ - message: string; + kind: "denied-interactively-by-user"; /** - * Server timestamp in milliseconds + * Optional feedback from the user explaining the denial */ - timestamp: number; + feedback?: string; /** - * Server protocol version number + * Whether to force-reject the current agent turn */ - protocolVersion: number; + forceReject?: boolean; } /** - * Existence, contents, and resolved path of the session plan file. + * Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PlanReadResult". + * via the `definition` "PermissionDecisionDeniedByContentExclusionPolicy". */ -export interface PlanReadResult { - /** - * Whether the plan file exists in the workspace - */ - exists: boolean; +export interface PermissionDecisionDeniedByContentExclusionPolicy { /** - * The content of the plan file, or null if it does not exist + * Denied by the organization's content exclusion policy */ - content: string | null; + kind: "denied-by-content-exclusion-policy"; /** - * Absolute file path of the plan file, or null if workspace is not enabled + * File path that triggered the exclusion */ - path: string | null; -} -/** - * Replacement contents to write to the session plan file. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PlanUpdateRequest". - */ -export interface PlanUpdateRequest { + path: string; /** - * The new content for the plan file + * Human-readable explanation of why the path was excluded */ - content: string; + message: string; } /** - * Schema for the `Plugin` type. + * Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "Plugin". + * via the `definition` "PermissionDecisionDeniedByPermissionRequestHook". */ -/** @experimental */ -export interface Plugin { - /** - * Plugin name - */ - name: string; +export interface PermissionDecisionDeniedByPermissionRequestHook { /** - * Marketplace the plugin came from + * Denied by a permission request hook registered by an extension or plugin */ - marketplace: string; + kind: "denied-by-permission-request-hook"; /** - * Installed version + * Optional message from the hook explaining the denial */ - version?: string; + message?: string; /** - * Whether the plugin is currently enabled + * Whether to interrupt the current agent turn */ - enabled: boolean; + interrupt?: boolean; } /** - * Plugins installed for the session, with their enabled state and version metadata. + * Pending permission request ID and the decision to apply (approve/reject and scope). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "PluginList". + * via the `definition` "PermissionDecisionRequest". */ -/** @experimental */ -export interface PluginList { +export interface PermissionDecisionRequest { /** - * Installed plugins + * Request ID of the pending permission request */ - plugins: Plugin[]; + requestId: string; + result: PermissionDecision; } /** - * Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. + * Directory path to add to the session's allowed directories. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "RemoteEnableRequest". + * via the `definition` "PermissionPathsAddParams". */ -/** @experimental */ -export interface RemoteEnableRequest { - mode?: RemoteSessionMode; +export interface PermissionPathsAddParams { + /** + * Directory to add to the allow-list. The runtime resolves and validates the path before adding. + */ + path: string; } /** - * GitHub URL for the session and a flag indicating whether remote steering is enabled. + * Path to evaluate against the session's allowed directories. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "RemoteEnableResult". + * via the `definition` "PermissionPathsAllowedCheckParams". */ -/** @experimental */ -export interface RemoteEnableResult { - /** - * GitHub frontend URL for this session - */ - url?: string; +export interface PermissionPathsAllowedCheckParams { /** - * Whether remote steering is enabled + * Path to check against the session's allowed directories */ - remoteSteerable: boolean; + path: string; } /** - * Remote session connection result. + * Indicates whether the supplied path is within the session's allowed directories. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "RemoteSessionConnectionResult". + * via the `definition` "PermissionPathsAllowedCheckResult". */ -/** @experimental */ -export interface RemoteSessionConnectionResult { +export interface PermissionPathsAllowedCheckResult { /** - * SDK session ID for the connected remote session. + * Whether the path is within the session's allowed directories */ - sessionId: string; - metadata: ConnectedRemoteSessionMetadata; + allowed: boolean; } /** - * Schema for the `ServerSkill` type. + * If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ServerSkill". + * via the `definition` "PermissionPathsConfig". */ -export interface ServerSkill { - /** - * Unique identifier for the skill - */ - name: string; - /** - * Description of what the skill does - */ - description: string; - source: SkillSource; +export interface PermissionPathsConfig { /** - * Whether the skill can be invoked by the user as a slash command + * If true, the runtime allows access to all paths without prompting. Equivalent to constructing an UnrestrictedPathManager. */ - userInvocable: boolean; + unrestricted?: boolean; /** - * Whether the skill is currently enabled (based on global config) + * Additional directories to allow tool access to (in addition to the session's working directory). When `unrestricted` is true, these are still pre-populated on the UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention completion). */ - enabled: boolean; + additionalDirectories?: string[]; /** - * Absolute path to the skill file + * Whether to include the system temp directory in the allowed list (defaults to true). Ignored when `unrestricted` is true. */ - path?: string; + includeTempDirectory?: boolean; /** - * The project path this skill belongs to (only for project/inherited skills) + * Workspace root path (special-cased to be allowed even before the directory exists). Ignored when `unrestricted` is true. */ - projectPath?: string; + workspacePath?: string; } /** - * Skills discovered across global and project sources. + * Snapshot of the session's allow-listed directories and primary working directory. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "ServerSkillList". + * via the `definition` "PermissionPathsList". */ -export interface ServerSkillList { +export interface PermissionPathsList { /** - * All discovered skills across all sources + * All directories currently allowed for tool access on this session. */ - skills: ServerSkill[]; + directories: string[]; + /** + * The primary working directory for this session. + */ + primary: string; } /** - * Authentication status and account metadata for the session. + * Directory path to set as the session's new primary working directory. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionAuthStatus". + * via the `definition` "PermissionPathsUpdatePrimaryParams". */ -export interface SessionAuthStatus { - /** - * Whether the session has resolved authentication - */ - isAuthenticated: boolean; - authType?: AuthInfoType; - /** - * Authentication host URL - */ - host?: string; - /** - * Authenticated login/username, if available - */ - login?: string; - /** - * Human-readable authentication status description - */ - statusMessage?: string; +export interface PermissionPathsUpdatePrimaryParams { /** - * Copilot plan tier (e.g., individual_pro, business) + * Directory to set as the new primary working directory for the session's permission policy. */ - copilotPlan?: string; + path: string; } /** - * File path, content to append, and optional mode for the client-provided session filesystem. + * Path to evaluate against the session's workspace (primary) directory. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsAppendFileRequest". + * via the `definition` "PermissionPathsWorkspaceCheckParams". */ -export interface SessionFsAppendFileRequest { - /** - * Target session identifier - */ - sessionId: string; +export interface PermissionPathsWorkspaceCheckParams { /** - * Path using SessionFs conventions + * Path to check against the session workspace directory */ path: string; - /** - * Content to append - */ - content: string; - /** - * Optional POSIX-style mode for newly created files - */ - mode?: number; } /** - * Describes a filesystem error. + * Indicates whether the supplied path is within the session's workspace directory. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsError". + * via the `definition` "PermissionPathsWorkspaceCheckResult". */ -export interface SessionFsError { - code: SessionFsErrorCode; +export interface PermissionPathsWorkspaceCheckResult { /** - * Free-form detail about the error, for logging/diagnostics + * Whether the path is within the session workspace directory */ - message?: string; + allowed: boolean; } /** - * Path to test for existence in the client-provided session filesystem. + * Notification payload describing the permission prompt that the client just rendered. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsExistsRequest". + * via the `definition` "PermissionPromptShownNotification". */ -export interface SessionFsExistsRequest { - /** - * Target session identifier - */ - sessionId: string; +export interface PermissionPromptShownNotification { /** - * Path using SessionFs conventions + * Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). */ - path: string; + message: string; } /** - * Indicates whether the requested path exists in the client-provided session filesystem. + * Indicates whether the permission decision was applied; false when the request was already resolved. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsExistsResult". + * via the `definition` "PermissionRequestResult". */ -export interface SessionFsExistsResult { +export interface PermissionRequestResult { /** - * Whether the path exists + * Whether the permission request was handled successfully */ - exists: boolean; + success: boolean; } /** - * Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. + * If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsMkdirRequest". + * via the `definition` "PermissionRulesSet". */ -export interface SessionFsMkdirRequest { - /** - * Target session identifier - */ - sessionId: string; - /** - * Path using SessionFs conventions - */ - path: string; +export interface PermissionRulesSet { /** - * Create parent directories as needed + * Rules that auto-approve matching requests */ - recursive?: boolean; + approved: PermissionRule[]; /** - * Optional POSIX-style mode for newly created directories + * Rules that auto-deny matching requests */ - mode?: number; + denied: PermissionRule[]; } /** - * Directory path whose entries should be listed from the client-provided session filesystem. + * Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReaddirRequest". + * via the `definition` "PermissionsConfigureAdditionalContentExclusionPolicy". */ -export interface SessionFsReaddirRequest { - /** - * Target session identifier - */ - sessionId: string; - /** - * Path using SessionFs conventions - */ - path: string; +export interface PermissionsConfigureAdditionalContentExclusionPolicy { + rules: PermissionsConfigureAdditionalContentExclusionPolicyRule[]; + last_updated_at: string | number; + scope: PermissionsConfigureAdditionalContentExclusionPolicyScope; + [k: string]: unknown; } /** - * Names of entries in the requested directory, or a filesystem error if the read failed. + * Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReaddirResult". + * via the `definition` "PermissionsConfigureAdditionalContentExclusionPolicyRule". */ -export interface SessionFsReaddirResult { - /** - * Entry names in the directory - */ - entries: string[]; - error?: SessionFsError; +export interface PermissionsConfigureAdditionalContentExclusionPolicyRule { + paths: string[]; + ifAnyMatch?: string[]; + ifNoneMatch?: string[]; + source: PermissionsConfigureAdditionalContentExclusionPolicyRuleSource; + [k: string]: unknown; } /** - * Schema for the `SessionFsReaddirWithTypesEntry` type. + * Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReaddirWithTypesEntry". + * via the `definition` "PermissionsConfigureAdditionalContentExclusionPolicyRuleSource". */ -export interface SessionFsReaddirWithTypesEntry { - /** - * Entry name - */ +export interface PermissionsConfigureAdditionalContentExclusionPolicyRuleSource { name: string; - type: SessionFsReaddirWithTypesEntryType; + type: string; } /** - * Directory path whose entries (with type information) should be listed from the client-provided session filesystem. + * Patch of permission policy fields to apply (omit a field to leave it unchanged). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReaddirWithTypesRequest". + * via the `definition` "PermissionsConfigureParams". */ -export interface SessionFsReaddirWithTypesRequest { +export interface PermissionsConfigureParams { /** - * Target session identifier + * If specified, sets whether tool permission requests are auto-approved without prompting. Omit to leave the current value unchanged. */ - sessionId: string; + approveAllToolPermissionRequests?: boolean; /** - * Path using SessionFs conventions + * If specified, sets whether path/URL read permission requests are auto-approved. Omit to leave the current value unchanged. */ - path: string; -} -/** - * Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReaddirWithTypesResult". - */ -export interface SessionFsReaddirWithTypesResult { + approveAllReadPermissionRequests?: boolean; + rules?: PermissionRulesSet; + paths?: PermissionPathsConfig; + urls?: PermissionUrlsConfig; /** - * Directory entries with type information + * If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. */ - entries: SessionFsReaddirWithTypesEntry[]; - error?: SessionFsError; + additionalContentExclusionPolicies?: PermissionsConfigureAdditionalContentExclusionPolicy[]; } /** - * Path of the file to read from the client-provided session filesystem. + * If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReadFileRequest". + * via the `definition` "PermissionUrlsConfig". */ -export interface SessionFsReadFileRequest { +export interface PermissionUrlsConfig { /** - * Target session identifier + * If true, the runtime allows access to all URLs without prompting. Initial allow-list is ignored when this is true. */ - sessionId: string; + unrestricted?: boolean; /** - * Path using SessionFs conventions + * Initial list of allowed URL/domain patterns. Patterns may include path components. Ignored when `unrestricted` is true. */ - path: string; + initialAllowed?: string[]; } /** - * File content as a UTF-8 string, or a filesystem error if the read failed. + * Indicates whether the operation succeeded. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsReadFileResult". + * via the `definition` "PermissionsConfigureResult". */ -export interface SessionFsReadFileResult { +export interface PermissionsConfigureResult { /** - * File content as UTF-8 string + * Whether the operation succeeded */ - content: string; - error?: SessionFsError; + success: boolean; } /** - * Source and destination paths for renaming or moving an entry in the client-provided session filesystem. + * Scope and add/remove instructions for modifying session- or location-scoped permission rules. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsRenameRequest". + * via the `definition` "PermissionsModifyRulesParams". */ -export interface SessionFsRenameRequest { +export interface PermissionsModifyRulesParams { + scope: PermissionsModifyRulesScope; /** - * Target session identifier + * Rules to add to the scope. Applied before `remove`/`removeAll`. */ - sessionId: string; + add?: PermissionRule[]; /** - * Source path using SessionFs conventions + * Specific rules to remove from the scope. Ignored when `removeAll` is true. */ - src: string; + remove?: PermissionRule[]; /** - * Destination path using SessionFs conventions + * When true, removes every rule currently in the scope (after any `add` is applied). Useful for clearing the location scope wholesale. */ - dest: string; + removeAll?: boolean; } /** - * Path to remove from the client-provided session filesystem, with options for recursive removal and force. + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsModifyRulesResult". + */ +export interface PermissionsModifyRulesResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsNotifyPromptShownResult". + */ +export interface PermissionsNotifyPromptShownResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsPathsAddResult". + */ +export interface PermissionsPathsAddResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * No parameters; returns the session's allow-listed directories. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsPathsListRequest". + */ +export interface PermissionsPathsListRequest {} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsPathsUpdatePrimaryResult". + */ +export interface PermissionsPathsUpdatePrimaryResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * No parameters; returns currently-pending permission requests for the session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsPendingRequestsRequest". + */ +export interface PermissionsPendingRequestsRequest {} +/** + * No parameters; clears all session-scoped tool permission approvals. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsResetSessionApprovalsRequest". + */ +export interface PermissionsResetSessionApprovalsRequest {} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsResetSessionApprovalsResult". + */ +export interface PermissionsResetSessionApprovalsResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Allow-all toggle for tool permission requests, with an optional telemetry source. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsSetApproveAllRequest". + */ +export interface PermissionsSetApproveAllRequest { + /** + * Whether to auto-approve all tool permission requests + */ + enabled: boolean; + source?: PermissionsSetApproveAllSource; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsSetApproveAllResult". + */ +export interface PermissionsSetApproveAllResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Toggles whether permission prompts should be bridged into session events for this client. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsSetRequiredRequest". + */ +export interface PermissionsSetRequiredRequest { + /** + * Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). + */ + required: boolean; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsSetRequiredResult". + */ +export interface PermissionsSetRequiredResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Indicates whether the operation succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionsUrlsSetUnrestrictedModeResult". + */ +export interface PermissionsUrlsSetUnrestrictedModeResult { + /** + * Whether the operation succeeded + */ + success: boolean; +} +/** + * Whether the URL-permission policy should run in unrestricted mode. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PermissionUrlsSetUnrestrictedModeParams". + */ +export interface PermissionUrlsSetUnrestrictedModeParams { + /** + * Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. + */ + enabled: boolean; +} +/** + * Optional message to echo back to the caller. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PingRequest". + */ +export interface PingRequest { + /** + * Optional message to echo back + */ + message?: string; +} +/** + * Server liveness response, including the echoed message, current server timestamp, and protocol version. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PingResult". + */ +export interface PingResult { + /** + * Echoed message (or default greeting) + */ + message: string; + /** + * ISO 8601 timestamp when the server handled the ping + */ + timestamp: string; + /** + * Server protocol version number + */ + protocolVersion: number; +} +/** + * Existence, contents, and resolved path of the session plan file. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PlanReadResult". + */ +export interface PlanReadResult { + /** + * Whether the plan file exists in the workspace + */ + exists: boolean; + /** + * The content of the plan file, or null if it does not exist + */ + content: string | null; + /** + * Absolute file path of the plan file, or null if workspace is not enabled + */ + path: string | null; +} +/** + * Replacement contents to write to the session plan file. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PlanUpdateRequest". + */ +export interface PlanUpdateRequest { + /** + * The new content for the plan file + */ + content: string; +} +/** + * Schema for the `Plugin` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "Plugin". + */ +/** @experimental */ +export interface Plugin { + /** + * Plugin name + */ + name: string; + /** + * Marketplace the plugin came from + */ + marketplace: string; + /** + * Installed version + */ + version?: string; + /** + * Whether the plugin is currently enabled + */ + enabled: boolean; +} +/** + * Plugins installed for the session, with their enabled state and version metadata. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "PluginList". + */ +/** @experimental */ +export interface PluginList { + /** + * Installed plugins + */ + plugins: Plugin[]; +} +/** + * Schema for the `QueuePendingItems` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "QueuePendingItems". + */ +/** @experimental */ +export interface QueuePendingItems { + kind: QueuePendingItemsKind; + /** + * Human-readable text to display for this queue entry in the UI + */ + displayText: string; +} +/** + * Snapshot of the session's pending queued items and immediate-steering messages. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "QueuePendingItemsResult". + */ +/** @experimental */ +export interface QueuePendingItemsResult { + /** + * Pending queued items in submission order. Includes user messages, queued slash commands, and queued model changes; omits internal system items. + */ + items: QueuePendingItems[]; + /** + * Display text for messages currently in the immediate steering queue (interjections sent during a running turn). + */ + steeringMessages: string[]; +} +/** + * Indicates whether a user-facing pending item was removed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "QueueRemoveMostRecentResult". + */ +/** @experimental */ +export interface QueueRemoveMostRecentResult { + /** + * True if a user-facing pending item was removed (LIFO across both queues); false when no removable items remained. + */ + removed: boolean; +} +/** + * Event type to register consumer interest for, used by runtime gating logic. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RegisterEventInterestParams". + */ +/** @experimental */ +export interface RegisterEventInterestParams { + /** + * The event type the consumer wants the runtime to treat as 'observed' for behavior-switching gating. Some runtime code paths inspect whether any consumer is interested in a specific event type and choose a different implementation accordingly (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full interactive OAuth flow to the consumer; when no interest is registered the runtime installs a browserless fallback that silently reuses cached tokens). SDK clients that long-poll events do NOT automatically appear as listeners to these gating checks — they must explicitly call `registerInterest` for each event type they want the runtime to count as having a consumer. Multiple registrations for the same event type from the same or different consumers are tracked independently and must each be released. See: `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, `user_input.requested`, `elicitation.requested`, `command.queued`, `exit_plan_mode.requested`. + */ + eventType: string; +} +/** + * Opaque handle representing an event-type interest registration. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RegisterEventInterestResult". + */ +/** @experimental */ +export interface RegisterEventInterestResult { + /** + * Opaque handle for this registration. Pass to releaseInterest to release. Each call to registerInterest produces a fresh handle, even when the same eventType is registered multiple times. + */ + handle: string; +} +/** + * Opaque handle previously returned by `registerInterest` to release. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ReleaseEventInterestParams". + */ +/** @experimental */ +export interface ReleaseEventInterestParams { + /** + * Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown or already-released handle is a no-op (returns success). When the last outstanding handle for an event type is released, the runtime reverts to its 'no consumer' code path for that event type. + */ + handle: string; +} +/** + * Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RemoteEnableRequest". + */ +/** @experimental */ +export interface RemoteEnableRequest { + mode?: RemoteSessionMode; +} +/** + * GitHub URL for the session and a flag indicating whether remote steering is enabled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RemoteEnableResult". + */ +/** @experimental */ +export interface RemoteEnableResult { + /** + * GitHub frontend URL for this session + */ + url?: string; + /** + * Whether remote steering is enabled + */ + remoteSteerable: boolean; +} +/** + * New remote-steerability state to persist as a `session.remote_steerable_changed` event. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RemoteNotifySteerableChangedRequest". + */ +/** @experimental */ +export interface RemoteNotifySteerableChangedRequest { + /** + * Whether the session now supports remote steering via GitHub. The runtime persists this as a `session.remote_steerable_changed` event so resume/replay sees the up-to-date capability. + */ + remoteSteerable: boolean; +} +/** + * Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RemoteNotifySteerableChangedResult". + */ +/** @experimental */ +export interface RemoteNotifySteerableChangedResult {} +/** + * Remote session connection result. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "RemoteSessionConnectionResult". + */ +/** @experimental */ +export interface RemoteSessionConnectionResult { + /** + * SDK session ID for the connected remote session. + */ + sessionId: string; + metadata: ConnectedRemoteSessionMetadata; +} +/** + * Schema for the `ScheduleEntry` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ScheduleEntry". + */ +/** @experimental */ +export interface ScheduleEntry { + /** + * Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt from the event log). + */ + id: number; + /** + * Interval between scheduled ticks, in milliseconds. + */ + intervalMs: number; + /** + * Prompt text that gets enqueued on every tick. + */ + prompt: string; + /** + * Whether the schedule re-arms after each tick (`/every`) or fires once (`/after`). + */ + recurring: boolean; + /** + * Display-only label for the prompt as shown in the UI (e.g. `/skill-name` for a skill-invocation schedule). The actual enqueued prompt is `prompt`. + */ + displayPrompt?: string; + /** + * ISO 8601 timestamp when the next tick is scheduled to fire. + */ + nextRunAt: string; +} +/** + * Snapshot of the currently active recurring prompts for this session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ScheduleList". + */ +/** @experimental */ +export interface ScheduleList { + /** + * Active scheduled prompts, ordered by id. + */ + entries: ScheduleEntry[]; +} +/** + * Identifier of the scheduled prompt to remove. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ScheduleStopRequest". + */ +/** @experimental */ +export interface ScheduleStopRequest { + /** + * Id of the scheduled prompt to remove. + */ + id: number; +} +/** + * Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ScheduleStopResult". + */ +/** @experimental */ +export interface ScheduleStopResult { + entry?: ScheduleEntry; +} +/** + * File attachment + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentFile". + */ +export interface SendAttachmentFile { + /** + * Attachment type discriminator + */ + type: "file"; + /** + * Absolute file path + */ + path: string; + /** + * User-facing display name for the attachment + */ + displayName: string; + lineRange?: SendAttachmentFileLineRange; +} +/** + * Optional line range to scope the attachment to a specific section of the file + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentFileLineRange". + */ +export interface SendAttachmentFileLineRange { + /** + * Start line number (1-based) + */ + start: number; + /** + * End line number (1-based, inclusive) + */ + end: number; +} +/** + * Directory attachment + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentDirectory". + */ +export interface SendAttachmentDirectory { + /** + * Attachment type discriminator + */ + type: "directory"; + /** + * Absolute directory path + */ + path: string; + /** + * User-facing display name for the attachment + */ + displayName: string; +} +/** + * Code selection attachment from an editor + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentSelection". + */ +export interface SendAttachmentSelection { + /** + * Attachment type discriminator + */ + type: "selection"; + /** + * Absolute path to the file containing the selection + */ + filePath: string; + /** + * User-facing display name for the selection + */ + displayName: string; + /** + * The selected text content + */ + text: string; + selection: SendAttachmentSelectionDetails; +} +/** + * Position range of the selection within the file + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentSelectionDetails". + */ +export interface SendAttachmentSelectionDetails { + start: SendAttachmentSelectionDetailsStart; + end: SendAttachmentSelectionDetailsEnd; +} +/** + * Start position of the selection + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentSelectionDetailsStart". + */ +export interface SendAttachmentSelectionDetailsStart { + /** + * Start line number (0-based) + */ + line: number; + /** + * Start character offset within the line (0-based) + */ + character: number; +} +/** + * End position of the selection + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentSelectionDetailsEnd". + */ +export interface SendAttachmentSelectionDetailsEnd { + /** + * End line number (0-based) + */ + line: number; + /** + * End character offset within the line (0-based) + */ + character: number; +} +/** + * GitHub issue, pull request, or discussion reference + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentGithubReference". + */ +export interface SendAttachmentGithubReference { + /** + * Attachment type discriminator + */ + type: "github_reference"; + /** + * Issue, pull request, or discussion number + */ + number: number; + /** + * Title of the referenced item + */ + title: string; + referenceType: SendAttachmentGithubReferenceType; + /** + * Current state of the referenced item (e.g., open, closed, merged) + */ + state: string; + /** + * URL to the referenced item on GitHub + */ + url: string; +} +/** + * Blob attachment with inline base64-encoded data + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendAttachmentBlob". + */ +export interface SendAttachmentBlob { + /** + * Attachment type discriminator + */ + type: "blob"; + /** + * Base64-encoded content + */ + data: string; + /** + * MIME type of the inline data + */ + mimeType: string; + /** + * User-facing display name for the attachment + */ + displayName?: string; +} +/** + * Parameters for sending a user message to the session + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendRequest". + */ +export interface SendRequest { + /** + * The user message text + */ + prompt: string; + /** + * If provided, this is shown in the timeline instead of `prompt` + */ + displayPrompt?: string; + /** + * Optional attachments (files, directories, selections, blobs, GitHub references) to include with the message + */ + attachments?: SendAttachment[]; + mode?: SendMode; + /** + * If true, adds the message to the front of the queue instead of the end + */ + prepend?: boolean; + /** + * If false, this message will not trigger a Premium Request Unit charge. User messages default to billable. + */ + billable?: boolean; + /** + * If set, the request will fail if the named tool is not available when this message is among the user messages at the start of the current exchange + */ + requiredTool?: string; + /** + * Optional provenance tag copied to the resulting user.message event. Supported values are `system`, `command-*`, and `schedule-*`. + */ + source?: { + [k: string]: unknown; + }; + agentMode?: SendAgentMode; + /** + * Custom HTTP headers to include in outbound model requests for this turn. Merged with session-level provider headers; per-turn headers augment and overwrite session-level headers with the same key. + */ + requestHeaders?: { + [k: string]: string; + }; + /** + * W3C Trace Context traceparent header for distributed tracing of this agent turn + */ + traceparent?: string; + /** + * W3C Trace Context tracestate header for distributed tracing + */ + tracestate?: string; + /** + * If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. + */ + wait?: boolean; +} +/** + * Result of sending a user message + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SendResult". + */ +export interface SendResult { + /** + * Unique identifier assigned to the message + */ + messageId: string; +} +/** + * Schema for the `ServerSkill` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ServerSkill". + */ +export interface ServerSkill { + /** + * Unique identifier for the skill + */ + name: string; + /** + * Description of what the skill does + */ + description: string; + source: SkillSource; + /** + * Whether the skill can be invoked by the user as a slash command + */ + userInvocable: boolean; + /** + * Whether the skill is currently enabled (based on global config) + */ + enabled: boolean; + /** + * Absolute path to the skill file + */ + path?: string; + /** + * The project path this skill belongs to (only for project/inherited skills) + */ + projectPath?: string; +} +/** + * Skills discovered across global and project sources. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ServerSkillList". + */ +export interface ServerSkillList { + /** + * All discovered skills across all sources + */ + skills: ServerSkill[]; +} +/** + * Authentication status and account metadata for the session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionAuthStatus". + */ +export interface SessionAuthStatus { + /** + * Whether the session has resolved authentication + */ + isAuthenticated: boolean; + authType?: AuthInfoType; + /** + * Authentication host URL + */ + host?: string; + /** + * Authenticated login/username, if available + */ + login?: string; + /** + * Human-readable authentication status description + */ + statusMessage?: string; + /** + * Copilot plan tier (e.g., individual_pro, business) + */ + copilotPlan?: string; +} +/** + * Map of sessionId -> bytes freed by removing the session's workspace directory. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionBulkDeleteResult". + */ +/** @experimental */ +export interface SessionBulkDeleteResult { + /** + * Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions whose deletion failed are omitted from this map (failures are logged on the server but not surfaced per-id; check the map for absent IDs to detect them). + */ + freedBytes: { + [k: string]: number; + }; +} +/** + * Schema for the `SessionContext` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionContext". + */ +/** @experimental */ +export interface SessionContext { + /** + * Most recent working directory for this session + */ + cwd: string; + /** + * Git repository root, if the cwd was inside a git repo + */ + gitRoot?: string; + /** + * Repository slug in `owner/name` form, when known + */ + repository?: string; + hostType?: SessionContextHostType; + /** + * Active git branch + */ + branch?: string; +} +/** + * The same metadata records, with summary and context fields backfilled where available. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionEnrichMetadataResult". + */ +/** @experimental */ +export interface SessionEnrichMetadataResult { + /** + * Same records, with summary and context backfilled + */ + sessions: SessionMetadata[]; +} +/** + * Schema for the `SessionMetadata` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionMetadata". + */ +/** @experimental */ +export interface SessionMetadata { + /** + * Stable session identifier + */ + sessionId: string; + /** + * Session creation time as an ISO 8601 timestamp + */ + startTime: string; + /** + * Last-modified time of the session's persisted state, as ISO 8601 + */ + modifiedTime: string; + /** + * Short summary of the session, when one has been derived + */ + summary?: string; + /** + * Optional human-friendly name set via /rename + */ + name?: string; + /** + * True for remote (GitHub) sessions; false for local + */ + isRemote: boolean; + context?: SessionContext; + /** + * GitHub task ID, when this local session is bound to one. Only present for local sessions exported to remote control. + */ + mcTaskId?: string; +} +/** + * File path, content to append, and optional mode for the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsAppendFileRequest". + */ +export interface SessionFsAppendFileRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; + /** + * Content to append + */ + content: string; + /** + * Optional POSIX-style mode for newly created files + */ + mode?: number; +} +/** + * Describes a filesystem error. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsError". + */ +export interface SessionFsError { + code: SessionFsErrorCode; + /** + * Free-form detail about the error, for logging/diagnostics + */ + message?: string; +} +/** + * Path to test for existence in the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsExistsRequest". + */ +export interface SessionFsExistsRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; +} +/** + * Indicates whether the requested path exists in the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsExistsResult". + */ +export interface SessionFsExistsResult { + /** + * Whether the path exists + */ + exists: boolean; +} +/** + * Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsMkdirRequest". + */ +export interface SessionFsMkdirRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; + /** + * Create parent directories as needed + */ + recursive?: boolean; + /** + * Optional POSIX-style mode for newly created directories + */ + mode?: number; +} +/** + * Directory path whose entries should be listed from the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReaddirRequest". + */ +export interface SessionFsReaddirRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; +} +/** + * Names of entries in the requested directory, or a filesystem error if the read failed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReaddirResult". + */ +export interface SessionFsReaddirResult { + /** + * Entry names in the directory + */ + entries: string[]; + error?: SessionFsError; +} +/** + * Schema for the `SessionFsReaddirWithTypesEntry` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReaddirWithTypesEntry". + */ +export interface SessionFsReaddirWithTypesEntry { + /** + * Entry name + */ + name: string; + type: SessionFsReaddirWithTypesEntryType; +} +/** + * Directory path whose entries (with type information) should be listed from the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReaddirWithTypesRequest". + */ +export interface SessionFsReaddirWithTypesRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; +} +/** + * Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReaddirWithTypesResult". + */ +export interface SessionFsReaddirWithTypesResult { + /** + * Directory entries with type information + */ + entries: SessionFsReaddirWithTypesEntry[]; + error?: SessionFsError; +} +/** + * Path of the file to read from the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReadFileRequest". + */ +export interface SessionFsReadFileRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; +} +/** + * File content as a UTF-8 string, or a filesystem error if the read failed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsReadFileResult". + */ +export interface SessionFsReadFileResult { + /** + * File content as UTF-8 string + */ + content: string; + error?: SessionFsError; +} +/** + * Source and destination paths for renaming or moving an entry in the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsRenameRequest". + */ +export interface SessionFsRenameRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Source path using SessionFs conventions + */ + src: string; + /** + * Destination path using SessionFs conventions + */ + dest: string; +} +/** + * Path to remove from the client-provided session filesystem, with options for recursive removal and force. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "SessionFsRmRequest". */ -export interface SessionFsRmRequest { +export interface SessionFsRmRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; + /** + * Remove directories and their contents recursively + */ + recursive?: boolean; + /** + * Ignore errors if the path does not exist + */ + force?: boolean; +} +/** + * Optional capabilities declared by the provider + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSetProviderCapabilities". + */ +export interface SessionFsSetProviderCapabilities { + /** + * Whether the provider supports SQLite query/exists operations + */ + sqlite?: boolean; +} +/** + * Initial working directory, session-state path layout, and path conventions used to register the calling SDK client as the session filesystem provider. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSetProviderRequest". + */ +export interface SessionFsSetProviderRequest { + /** + * Initial working directory for sessions + */ + initialCwd: string; + /** + * Path within each session's SessionFs where the runtime stores files for that session + */ + sessionStatePath: string; + conventions: SessionFsSetProviderConventions; + capabilities?: SessionFsSetProviderCapabilities; +} +/** + * Indicates whether the calling client was registered as the session filesystem provider. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSetProviderResult". + */ +export interface SessionFsSetProviderResult { + /** + * Whether the provider was set successfully + */ + success: boolean; +} +/** + * Indicates whether the per-session SQLite database already exists. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSqliteExistsResult". + */ +export interface SessionFsSqliteExistsResult { + /** + * Whether the session database already exists + */ + exists: boolean; +} +/** + * SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSqliteQueryRequest". + */ +export interface SessionFsSqliteQueryRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * SQL query to execute + */ + query: string; + queryType: SessionFsSqliteQueryType; + /** + * Optional named bind parameters + */ + params?: { + [k: string]: string | number | null; + }; +} +/** + * Query results including rows, columns, and rows affected, or a filesystem error if execution failed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsSqliteQueryResult". + */ +export interface SessionFsSqliteQueryResult { + /** + * For SELECT: array of row objects. For others: empty array. + */ + rows: { + [k: string]: unknown; + }[]; + /** + * Column names from the result set + */ + columns: string[]; + /** + * Number of rows affected (for INSERT/UPDATE/DELETE) + */ + rowsAffected: number; + /** + * SQLite last_insert_rowid() value for INSERT. + */ + lastInsertRowid?: number; + error?: SessionFsError; +} +/** + * Path whose metadata should be returned from the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsStatRequest". + */ +export interface SessionFsStatRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; +} +/** + * Filesystem metadata for the requested path, or a filesystem error if the stat failed. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsStatResult". + */ +export interface SessionFsStatResult { + /** + * Whether the path is a file + */ + isFile: boolean; + /** + * Whether the path is a directory + */ + isDirectory: boolean; + /** + * File size in bytes + */ + size: number; + /** + * ISO 8601 timestamp of last modification + */ + mtime: string; + /** + * ISO 8601 timestamp of creation + */ + birthtime: string; + error?: SessionFsError; +} +/** + * File path, content to write, and optional mode for the client-provided session filesystem. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionFsWriteFileRequest". + */ +export interface SessionFsWriteFileRequest { + /** + * Target session identifier + */ + sessionId: string; + /** + * Path using SessionFs conventions + */ + path: string; + /** + * Content to write + */ + content: string; + /** + * Optional POSIX-style mode for newly created files + */ + mode?: number; +} +/** + * Schema for the `SessionInstalledPlugin` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionInstalledPlugin". + */ +/** @experimental */ +export interface SessionInstalledPlugin { + /** + * Plugin name + */ + name: string; + /** + * Marketplace the plugin came from (empty string for direct repo installs) + */ + marketplace: string; + /** + * Installed version, if known + */ + version?: string; + /** + * Installation timestamp (ISO-8601) + */ + installed_at: string; + /** + * Whether the plugin is currently enabled + */ + enabled: boolean; + /** + * Path where the plugin is cached locally + */ + cache_path?: string; + source?: SessionInstalledPluginSource; +} +/** + * Schema for the `SessionInstalledPluginSourceGithub` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionInstalledPluginSourceGithub". + */ +/** @experimental */ +export interface SessionInstalledPluginSourceGithub { + /** + * Constant value. Always "github". + */ + source: "github"; + repo: string; + ref?: string; + path?: string; +} +/** + * Schema for the `SessionInstalledPluginSourceUrl` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionInstalledPluginSourceUrl". + */ +/** @experimental */ +export interface SessionInstalledPluginSourceUrl { + /** + * Constant value. Always "url". + */ + source: "url"; + url: string; + ref?: string; + path?: string; +} +/** + * Schema for the `SessionInstalledPluginSourceLocal` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionInstalledPluginSourceLocal". + */ +/** @experimental */ +export interface SessionInstalledPluginSourceLocal { + /** + * Constant value. Always "local". + */ + source: "local"; + path: string; +} +/** + * Persisted sessions matching the filter, ordered most-recently-modified first. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionList". + */ +/** @experimental */ +export interface SessionList { + /** + * Sessions ordered most-recently-modified first + */ + sessions: SessionMetadata[]; +} +/** + * Queued repo-level startup prompts and the total hook command count after loading. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionLoadDeferredRepoHooksResult". + */ +/** @experimental */ +export interface SessionLoadDeferredRepoHooksResult { + /** + * Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo configs were pending, or when disableAllHooks is set. + */ + startupPrompts: string[]; + /** + * Total hook command count (user + plugin + repo) loaded for the session by this call. Captured atomically with startupPrompts so callers don't need to read a separate counter. + */ + hookCount: number; +} +/** + * Point-in-time snapshot of slow-changing session identifier and state fields + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionMetadataSnapshot". + */ +/** @experimental */ +export interface SessionMetadataSnapshot { + /** + * The unique identifier of the session + */ + sessionId: string; + /** + * ISO 8601 timestamp of when the session started + */ + startTime: string; + /** + * ISO 8601 timestamp of when the session's persisted state was last modified on disk. For new sessions, equals startTime. For resumed sessions, reflects the previous modification time at construction. + */ + modifiedTime: string; + /** + * Whether this is a remote session (i.e., one whose runtime executes elsewhere and is steered through this process) + */ + isRemote: boolean; + /** + * True when the session was detected to be in use by another process at construction time. Local consumers may surface a confirmation prompt before fully attaching. Always false for new sessions. + */ + alreadyInUse: boolean; + /** + * Absolute path to the session's workspace directory on disk, or null if the session has no associated workspace + */ + workspacePath: string | null; + /** + * User-provided name supplied at session construction (via `--name`), if any. Immutable after construction. + */ + initialName?: string; + remoteMetadata?: MetadataSnapshotRemoteMetadata; + /** + * Short human-readable summary of the session, if known. Omitted when no summary has been generated. + */ + summary?: string; + /** + * Absolute path to the session's current working directory + */ + workingDirectory: string; + currentMode: MetadataSnapshotCurrentMode; + /** + * Currently selected model identifier, if any + */ + selectedModel?: string; + /** + * Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). + */ + workspace?: WorkspaceSummary | null; +} +/** + * Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionPruneResult". + */ +/** @experimental */ +export interface SessionPruneResult { /** - * Target session identifier + * Session IDs that were deleted (always empty in dry-run mode) + */ + deleted: string[]; + /** + * Session IDs that would be deleted in dry-run mode (always empty otherwise) + */ + candidates: string[]; + /** + * Session IDs that were skipped (e.g., named sessions) + */ + skipped: string[]; + /** + * Total bytes freed (actual when not dry-run, projected when dry-run) + */ + freedBytes: number; + /** + * True when no deletions were actually performed + */ + dryRun: boolean; +} +/** + * Session IDs to close, deactivate, and delete from disk. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsBulkDeleteRequest". + */ +/** @experimental */ +export interface SessionsBulkDeleteRequest { + /** + * Session IDs to close, deactivate, and delete from disk + */ + sessionIds: string[]; +} +/** + * Session IDs to test for live in-use locks. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsCheckInUseRequest". + */ +/** @experimental */ +export interface SessionsCheckInUseRequest { + /** + * Session IDs to test for live in-use locks + */ + sessionIds: string[]; +} +/** + * Session IDs from the input set that are currently in use by another process. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsCheckInUseResult". + */ +/** @experimental */ +export interface SessionsCheckInUseResult { + /** + * Session IDs from the input set that are currently held by another running process via an alive lock file + */ + inUse: string[]; +} +/** + * Session ID to close. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsCloseRequest". + */ +/** @experimental */ +export interface SessionsCloseRequest { + /** + * Session ID to close */ sessionId: string; +} +/** + * Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsCloseResult". + */ +/** @experimental */ +export interface SessionsCloseResult {} +/** + * Session metadata records to enrich with summary and context information. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsEnrichMetadataRequest". + */ +/** @experimental */ +export interface SessionsEnrichMetadataRequest { /** - * Path using SessionFs conventions + * Session metadata records to enrich. Records that already have summary and context are returned unchanged. */ - path: string; + sessions: SessionMetadata[]; +} +/** + * New auth credentials to install on the session. Omit to leave credentials unchanged. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionSetCredentialsParams". + */ +export interface SessionSetCredentialsParams { + credentials?: AuthInfo; +} +/** + * Indicates whether the credential update succeeded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionSetCredentialsResult". + */ +export interface SessionSetCredentialsResult { /** - * Remove directories and their contents recursively + * Whether the operation succeeded */ - recursive?: boolean; + success: boolean; +} +/** + * UUID prefix to resolve to a unique session ID. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsFindByPrefixRequest". + */ +/** @experimental */ +export interface SessionsFindByPrefixRequest { /** - * Ignore errors if the path does not exist + * UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when there is no match or the prefix matches multiple sessions. */ - force?: boolean; + prefix: string; } /** - * Optional capabilities declared by the provider + * Session ID matching the prefix, omitted when no unique match exists. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSetProviderCapabilities". + * via the `definition` "SessionsFindByPrefixResult". */ -export interface SessionFsSetProviderCapabilities { +/** @experimental */ +export interface SessionsFindByPrefixResult { /** - * Whether the provider supports SQLite query/exists operations + * Omitted when no unique session matches the prefix (no match or ambiguous) */ - sqlite?: boolean; + sessionId?: string; +} +/** + * GitHub task ID to look up. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsFindByTaskIDRequest". + */ +/** @experimental */ +export interface SessionsFindByTaskIDRequest { + /** + * GitHub task ID to look up + */ + taskId: string; +} +/** + * ID of the local session bound to the given GitHub task, or omitted when none. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsFindByTaskIDResult". + */ +/** @experimental */ +export interface SessionsFindByTaskIDResult { + /** + * Omitted when no local session is bound to that GitHub task + */ + sessionId?: string; +} +/** + * Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsForkRequest". + */ +/** @experimental */ +export interface SessionsForkRequest { + /** + * 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; + /** + * Optional friendly name to assign to the forked session. + */ + name?: string; +} +/** + * Identifier and optional friendly name assigned to the newly forked session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsForkResult". + */ +/** @experimental */ +export interface SessionsForkResult { + /** + * The new forked session's ID + */ + sessionId: string; + /** + * Friendly name assigned to the forked session, if any. + */ + name?: string; +} +/** + * Session ID whose event-log file path to compute. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetEventFilePathRequest". + */ +/** @experimental */ +export interface SessionsGetEventFilePathRequest { + /** + * Session ID whose event-log file path to compute + */ + sessionId: string; +} +/** + * Absolute path to the session's events.jsonl file on disk. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetEventFilePathResult". + */ +/** @experimental */ +export interface SessionsGetEventFilePathResult { + /** + * Absolute path to the session's events.jsonl file + */ + filePath: string; +} +/** + * Optional working-directory context used to score session relevance. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetLastForContextRequest". + */ +/** @experimental */ +export interface SessionsGetLastForContextRequest { + context?: SessionContext; +} +/** + * Most-relevant session ID for the supplied context, or omitted when no sessions exist. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetLastForContextResult". + */ +/** @experimental */ +export interface SessionsGetLastForContextResult { + /** + * Most-relevant session ID for the supplied context, or omitted when no sessions exist + */ + sessionId?: string; +} +/** + * Session ID to look up the persisted remote-steerable flag for. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetPersistedRemoteSteerableRequest". + */ +/** @experimental */ +export interface SessionsGetPersistedRemoteSteerableRequest { + /** + * Session ID to look up the persisted remote-steerable flag for + */ + sessionId: string; +} +/** + * The session's persisted remote-steerable flag, or omitted when no value has been persisted. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsGetPersistedRemoteSteerableResult". + */ +/** @experimental */ +export interface SessionsGetPersistedRemoteSteerableResult { + /** + * The session's persisted remote-steerable flag if recorded; omitted when no value has been persisted + */ + remoteSteerable?: boolean; +} +/** + * Map of sessionId -> on-disk size in bytes for each session's workspace directory. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionSizes". + */ +/** @experimental */ +export interface SessionSizes { + /** + * Map of sessionId -> on-disk size in bytes for the session's workspace directory + */ + sizes: { + [k: string]: number; + }; +} +/** + * Optional metadata-load limit and context filter applied to the returned sessions. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsListRequest". + */ +/** @experimental */ +export interface SessionsListRequest { + /** + * When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. + */ + metadataLimit?: number; + /** + * Optional filter applied to the returned sessions + */ + filter?: { + /** + * Match sessions whose context.cwd equals this value + */ + cwd?: string; + /** + * Match sessions whose context.gitRoot equals this value + */ + gitRoot?: string; + /** + * Match sessions whose context.repository equals this value + */ + repository?: string; + /** + * Match sessions whose context.branch equals this value + */ + branch?: string; + }; +} +/** + * Active session ID whose deferred repo-level hooks should be loaded. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsLoadDeferredRepoHooksRequest". + */ +/** @experimental */ +export interface SessionsLoadDeferredRepoHooksRequest { + /** + * Active session ID whose deferred repo-level hooks should be loaded + */ + sessionId: string; +} +/** + * Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsPruneOldRequest". + */ +/** @experimental */ +export interface SessionsPruneOldRequest { + /** + * Delete sessions whose modifiedTime is at least this many days old + */ + olderThanDays: number; + /** + * When true, only report what would be deleted without performing any deletion + */ + dryRun?: boolean; + /** + * When true, named sessions (set via /rename) are also eligible for pruning + */ + includeNamed?: boolean; + /** + * Session IDs that should never be considered for pruning + */ + excludeSessionIds?: string[]; +} +/** + * Session ID whose in-use lock should be released. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsReleaseLockRequest". + */ +/** @experimental */ +export interface SessionsReleaseLockRequest { + /** + * Session ID whose in-use lock should be released + */ + sessionId: string; } /** - * Initial working directory, session-state path layout, and path conventions used to register the calling SDK client as the session filesystem provider. + * Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsReleaseLockResult". + */ +/** @experimental */ +export interface SessionsReleaseLockResult {} +/** + * Active session ID and an optional flag for deferring repo-level hooks until folder trust. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSetProviderRequest". + * via the `definition` "SessionsReloadPluginHooksRequest". */ -export interface SessionFsSetProviderRequest { +/** @experimental */ +export interface SessionsReloadPluginHooksRequest { /** - * Initial working directory for sessions + * Active session ID to reload hooks for */ - initialCwd: string; + sessionId: string; /** - * Path within each session's SessionFs where the runtime stores files for that session + * When true, skip repo-level hooks. Use before folder trust is confirmed; loadDeferredRepoHooks loads them post-trust. */ - sessionStatePath: string; - conventions: SessionFsSetProviderConventions; - capabilities?: SessionFsSetProviderCapabilities; + deferRepoHooks?: boolean; } /** - * Indicates whether the calling client was registered as the session filesystem provider. + * Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSetProviderResult". + * via the `definition` "SessionsReloadPluginHooksResult". */ -export interface SessionFsSetProviderResult { +/** @experimental */ +export interface SessionsReloadPluginHooksResult {} +/** + * Session ID whose pending events should be flushed to disk. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsSaveRequest". + */ +/** @experimental */ +export interface SessionsSaveRequest { /** - * Whether the provider was set successfully + * Session ID whose pending events should be flushed to disk */ - success: boolean; + sessionId: string; } /** - * Indicates whether the per-session SQLite database already exists. + * Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSqliteExistsResult". + * via the `definition` "SessionsSaveResult". */ -export interface SessionFsSqliteExistsResult { +/** @experimental */ +export interface SessionsSaveResult {} +/** + * Manager-wide additional plugins to register; replaces any previously-configured set. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionsSetAdditionalPluginsRequest". + */ +/** @experimental */ +export interface SessionsSetAdditionalPluginsRequest { /** - * Whether the session database already exists + * Manager-wide additional plugins to register. Replaces any previously-configured set. Pass an empty array to clear. */ - exists: boolean; + plugins: InstalledPlugin[]; } /** - * SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. + * Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSqliteQueryRequest". + * via the `definition` "SessionsSetAdditionalPluginsResult". */ -export interface SessionFsSqliteQueryRequest { +/** @experimental */ +export interface SessionsSetAdditionalPluginsResult {} +/** + * Patch of mutable session options to apply to the running session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SessionUpdateOptionsParams". + */ +/** @experimental */ +export interface SessionUpdateOptionsParams { /** - * Target session identifier + * The model ID to use for assistant turns. */ - sessionId: string; + model?: string; /** - * SQL query to execute + * Reasoning effort for the selected model (model-defined enum). */ - query: string; - queryType: SessionFsSqliteQueryType; + reasoningEffort?: string; /** - * Optional named bind parameters + * Identifier of the client driving the session. */ - params?: { - [k: string]: string | number | null; + clientName?: string; + /** + * Identifier sent to LSP-style integrations. + */ + lspClientName?: string; + /** + * Stable integration identifier used for analytics and rate-limit attribution. + */ + integrationId?: string; + /** + * Map of feature-flag IDs to their boolean enabled state. + */ + featureFlags?: { + [k: string]: boolean; }; -} -/** - * Query results including rows, columns, and rows affected, or a filesystem error if execution failed. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsSqliteQueryResult". - */ -export interface SessionFsSqliteQueryResult { /** - * For SELECT: array of row objects. For others: empty array. + * Whether experimental capabilities are enabled. */ - rows: { + isExperimentalMode?: boolean; + /** + * Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the runtime. + */ + provider?: { [k: string]: unknown; - }[]; + }; /** - * Column names from the result set + * Absolute working-directory path for shell tools. */ - columns: string[]; + workingDirectory?: string; /** - * Number of rows affected (for INSERT/UPDATE/DELETE) + * Allowlist of tool names available to this session. */ - rowsAffected: number; + availableTools?: string[]; /** - * Last inserted row ID (for INSERT) + * Denylist of tool names for this session. */ - lastInsertRowid?: number; - error?: SessionFsError; -} -/** - * Path whose metadata should be returned from the client-provided session filesystem. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsStatRequest". - */ -export interface SessionFsStatRequest { + excludedTools?: string[]; /** - * Target session identifier + * Whether shell-script safety heuristics are enabled. */ - sessionId: string; + enableScriptSafety?: boolean; /** - * Path using SessionFs conventions + * Shell init profile (`None` or `NonInteractive`). */ - path: string; -} -/** - * Filesystem metadata for the requested path, or a filesystem error if the stat failed. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsStatResult". - */ -export interface SessionFsStatResult { + shellInitProfile?: string; /** - * Whether the path is a file + * Per-shell process flags (e.g., `pwsh` arguments). */ - isFile: boolean; + shellProcessFlags?: string[]; /** - * Whether the path is a directory + * Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. */ - isDirectory: boolean; + sandboxConfig?: { + [k: string]: unknown; + }; /** - * File size in bytes + * Whether interactive shell sessions are logged. */ - size: number; + logInteractiveShells?: boolean; + envValueMode?: OptionsUpdateEnvValueMode; /** - * ISO 8601 timestamp of last modification + * Additional directories to search for skills. */ - mtime: string; + skillDirectories?: string[]; /** - * ISO 8601 timestamp of creation + * Skill IDs that should be excluded from this session. */ - birthtime: string; - error?: SessionFsError; -} -/** - * File path, content to write, and optional mode for the client-provided session filesystem. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionFsWriteFileRequest". - */ -export interface SessionFsWriteFileRequest { + disabledSkills?: string[]; /** - * Target session identifier + * Whether to discover custom instructions on demand after successful file views (AGENTS.md / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. */ - sessionId: string; + enableOnDemandInstructionDiscovery?: boolean; /** - * Path using SessionFs conventions + * Full set of installed plugins for the session. Replaces the existing list; the runtime invalidates the skills cache only when the list materially changes. */ - path: string; + installedPlugins?: SessionInstalledPlugin[]; /** - * Content to write + * Whether to default custom agents to local-only execution. */ - content: string; + customAgentsLocalOnly?: boolean; /** - * Optional POSIX-style mode for newly created files + * Whether to skip loading custom instruction sources. */ - mode?: number; -} -/** - * Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. - * - * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionsForkRequest". - */ -/** @experimental */ -export interface SessionsForkRequest { + skipCustomInstructions?: boolean; /** - * Source session ID to fork from + * Instruction source IDs to exclude from the system prompt. */ - sessionId: string; + disabledInstructionSources?: string[]; /** - * Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. + * Whether to include the `Co-authored-by` trailer in commit messages. */ - toEventId?: string; + coauthorEnabled?: boolean; /** - * Optional friendly name to assign to the forked session. + * Optional path for trajectory output. */ - name?: string; + trajectoryFile?: string; + /** + * Whether to stream model responses. + */ + enableStreaming?: boolean; + /** + * Override URL for the Copilot API endpoint. + */ + copilotUrl?: string; + /** + * Whether to disable the `ask_user` tool (encourages autonomous behavior). + */ + askUserDisabled?: boolean; + /** + * Whether to allow auto-mode continuation across turns. + */ + continueOnAutoMode?: boolean; + /** + * Whether the session is running in an interactive UI. + */ + runningInInteractiveMode?: boolean; + /** + * Whether to surface reasoning-summary events from the model. + */ + enableReasoningSummaries?: boolean; + /** + * Runtime context discriminator (e.g., `cli`, `actions`). + */ + agentContext?: string; + /** + * Override directory for the session-events log. When unset, the runtime's default events log directory is used. + */ + eventsLogDirectory?: string; + /** + * Additional content-exclusion policies to merge into the session's policy set. Opaque shape; see `ContentExclusionApiResponse` in the runtime. + */ + additionalContentExclusionPolicies?: unknown[]; + /** + * Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the per-session schedule registry; this flag only controls tool exposure (typically gated to staff users). + */ + manageScheduleEnabled?: boolean; } /** - * Identifier and optional friendly name assigned to the newly forked session. + * Indicates whether the session options patch was applied successfully. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "SessionsForkResult". + * via the `definition` "SessionUpdateOptionsResult". */ /** @experimental */ -export interface SessionsForkResult { - /** - * The new forked session's ID - */ - sessionId: string; +export interface SessionUpdateOptionsResult { /** - * Friendly name assigned to the forked session, if any. + * Whether the operation succeeded */ - name?: string; + success: boolean; } /** * Shell command to run, with optional working directory and timeout in milliseconds. @@ -3058,6 +6255,19 @@ export interface ShellKillResult { */ killed: boolean; } +/** + * Parameters for shutting down the session + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ShutdownRequest". + */ +export interface ShutdownRequest { + type?: ShutdownType; + /** + * Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. + */ + reason?: string; +} /** * Schema for the `Skill` type. * @@ -3087,6 +6297,10 @@ export interface Skill { * Absolute path to the skill file */ path?: string; + /** + * Name of the plugin that provides the skill, when source is 'plugin' + */ + pluginName?: string; } /** * Skills available to the session, with their enabled state. @@ -3155,6 +6369,48 @@ export interface SkillsEnableRequest { */ name: string; } +/** + * Skills invoked during this session, ordered by invocation time (most recent last). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SkillsGetInvokedResult". + */ +/** @experimental */ +export interface SkillsGetInvokedResult { + /** + * Skills invoked during this session, ordered by invocation time (most recent last) + */ + skills: SkillsInvokedSkill[]; +} +/** + * Schema for the `SkillsInvokedSkill` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "SkillsInvokedSkill". + */ +/** @experimental */ +export interface SkillsInvokedSkill { + /** + * Unique identifier for the skill + */ + name: string; + /** + * Path to the SKILL.md file + */ + path: string; + /** + * Full content of the skill file + */ + content: string; + /** + * Tools that should be auto-approved when this skill is active, captured at invocation time + */ + allowedTools?: string[]; + /** + * Turn number when the skill was invoked + */ + invokedAtTurn: number; +} /** * Diagnostics from reloading skill definitions, with warnings and errors as separate lists. * @@ -3388,24 +6644,70 @@ export interface TaskList { * via the `definition` "TasksCancelRequest". */ /** @experimental */ -export interface TasksCancelRequest { +export interface TasksCancelRequest { + /** + * Task identifier + */ + id: string; +} +/** + * Indicates whether the background task was successfully cancelled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksCancelResult". + */ +/** @experimental */ +export interface TasksCancelResult { + /** + * Whether the task was successfully cancelled + */ + cancelled: boolean; +} +/** + * The first sync-waiting task that can currently be promoted to background mode. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksGetCurrentPromotableResult". + */ +/** @experimental */ +export interface TasksGetCurrentPromotableResult { + task?: TaskInfo; +} +/** + * Identifier of the background task to fetch progress for. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksGetProgressRequest". + */ +/** @experimental */ +export interface TasksGetProgressRequest { + /** + * Task identifier (agent ID or shell ID) + */ + id: string; +} +/** + * Progress information for the task, or null when no task with that ID is tracked. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksGetProgressResult". + */ +/** @experimental */ +export interface TasksGetProgressResult { /** - * Task identifier + * Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. */ - id: string; + progress?: TaskProgress | null; } /** - * Indicates whether the background task was successfully cancelled. + * The promoted task as it now exists in background mode, omitted if no promotable task was waiting. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema - * via the `definition` "TasksCancelResult". + * via the `definition` "TasksPromoteCurrentToBackgroundResult". */ /** @experimental */ -export interface TasksCancelResult { - /** - * Whether the task was successfully cancelled - */ - cancelled: boolean; +export interface TasksPromoteCurrentToBackgroundResult { + task?: TaskInfo; } /** * Identifier of the task to promote to background mode. @@ -3433,6 +6735,14 @@ export interface TasksPromoteToBackgroundResult { */ promoted: boolean; } +/** + * Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksRefreshResult". + */ +/** @experimental */ +export interface TasksRefreshResult {} /** * Identifier of the completed or cancelled task to remove from tracking. * @@ -3539,6 +6849,29 @@ export interface TasksStartAgentResult { */ agentId: string; } +/** + * Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TasksWaitForPendingResult". + */ +/** @experimental */ +export interface TasksWaitForPendingResult {} +/** + * Feature override key/value pairs to attach to subsequent telemetry events from this session. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "TelemetrySetFeatureOverridesRequest". + */ +/** @experimental */ +export interface TelemetrySetFeatureOverridesRequest { + /** + * Override key/value pairs to attach to subsequent telemetry events from this session. Replaces any previously-set overrides. + */ + features: { + [k: string]: string; + }; +} /** * Schema for the `Tool` type. * @@ -3581,6 +6914,13 @@ export interface ToolList { */ tools: Tool[]; } +/** + * Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "ToolsInitializeAndValidateResult". + */ +export interface ToolsInitializeAndValidateResult {} /** * Optional model identifier whose tool overrides should be applied to the listing. * @@ -3931,6 +7271,40 @@ export interface UIElicitationResult { */ success: boolean; } +/** + * Schema for the `UIExitPlanModeResponse` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIExitPlanModeResponse". + */ +export interface UIExitPlanModeResponse { + /** + * Whether the plan was approved. + */ + approved: boolean; + selectedAction?: UIExitPlanModeAction; + /** + * Whether subsequent edits should be auto-approved without confirmation. + */ + autoApproveEdits?: boolean; + /** + * Feedback from the user when they declined the plan or requested changes. + */ + feedback?: string; +} +/** + * Request ID of a pending `auto_mode_switch.requested` event and the user's response. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingAutoModeSwitchRequest". + */ +export interface UIHandlePendingAutoModeSwitchRequest { + /** + * The unique request ID from the auto_mode_switch.requested event + */ + requestId: string; + response: UIAutoModeSwitchResponse; +} /** * Pending elicitation request ID and the user's response (accept/decline/cancel + form values). * @@ -3944,6 +7318,118 @@ export interface UIHandlePendingElicitationRequest { requestId: string; result: UIElicitationResponse; } +/** + * Request ID of a pending `exit_plan_mode.requested` event and the user's response. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingExitPlanModeRequest". + */ +export interface UIHandlePendingExitPlanModeRequest { + /** + * The unique request ID from the exit_plan_mode.requested event + */ + requestId: string; + response: UIExitPlanModeResponse; +} +/** + * Indicates whether the pending UI request was resolved by this call. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingResult". + */ +export interface UIHandlePendingResult { + /** + * True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + */ + success: boolean; +} +/** + * Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingSamplingRequest". + */ +export interface UIHandlePendingSamplingRequest { + /** + * The unique request ID from the sampling.requested event + */ + requestId: string; + response?: UIHandlePendingSamplingResponse; +} +/** + * Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingSamplingResponse". + */ +export interface UIHandlePendingSamplingResponse { + [k: string]: unknown; +} +/** + * Request ID of a pending `user_input.requested` event and the user's response. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIHandlePendingUserInputRequest". + */ +export interface UIHandlePendingUserInputRequest { + /** + * The unique request ID from the user_input.requested event + */ + requestId: string; + response: UIUserInputResponse; +} +/** + * Schema for the `UIUserInputResponse` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIUserInputResponse". + */ +export interface UIUserInputResponse { + /** + * The user's answer text + */ + answer: string; + /** + * True if the user typed a freeform response, false if they selected a presented choice. Used by telemetry to differentiate between free text input and choice selection. + */ + wasFreeform: boolean; +} +/** + * Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIRegisterDirectAutoModeSwitchHandlerResult". + */ +export interface UIRegisterDirectAutoModeSwitchHandlerResult { + /** + * Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. + */ + handle: string; +} +/** + * Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIUnregisterDirectAutoModeSwitchHandlerRequest". + */ +export interface UIUnregisterDirectAutoModeSwitchHandlerRequest { + /** + * Handle previously returned by `registerDirectAutoModeSwitchHandler` + */ + handle: string; +} +/** + * Indicates whether the handle was active and the registration count was decremented. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "UIUnregisterDirectAutoModeSwitchHandlerResult". + */ +export interface UIUnregisterDirectAutoModeSwitchHandlerResult { + /** + * True if the handle was active and decremented the counter; false if the handle was unknown. + */ + unregistered: boolean; +} /** * Accumulated session usage metrics, including premium request cost, token counts, model breakdown, and code-change totals. * @@ -3975,9 +7461,9 @@ export interface UsageGetMetricsResult { */ totalApiDurationMs: number; /** - * Session start timestamp (epoch milliseconds) + * ISO 8601 timestamp when the session started */ - sessionStartTime: number; + sessionStartTime: string; codeChanges: UsageMetricsCodeChanges; /** * Per-model token and request metrics, keyed by model identifier @@ -4031,6 +7517,10 @@ export interface UsageMetricsCodeChanges { * Number of distinct files modified */ filesModifiedCount: number; + /** + * Distinct file paths modified during the session + */ + filesModified: string[]; } /** * Schema for the `UsageMetricsModelMetric` type. @@ -4112,6 +7602,26 @@ export interface UsageMetricsModelMetricTokenDetail { */ tokenCount: number; } +/** + * Schema for the `WorkspacesCheckpoints` type. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesCheckpoints". + */ +export interface WorkspacesCheckpoints { + /** + * Checkpoint number assigned by the workspace manager + */ + number: number; + /** + * Human-readable checkpoint title + */ + title: string; + /** + * Filename of the checkpoint within the workspace checkpoints directory + */ + filename: string; +} /** * Relative path and UTF-8 content for the workspace file to create or overwrite. * @@ -4129,7 +7639,7 @@ export interface WorkspacesCreateFileRequest { content: string; } /** - * Current workspace metadata for the session, or null when not available. + * Current workspace metadata for the session, including its absolute filesystem path when available. * * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema * via the `definition` "WorkspacesGetWorkspaceResult". @@ -4156,6 +7666,22 @@ export interface WorkspacesGetWorkspaceResult { mc_last_event_id?: string; chronicle_sync_dismissed?: boolean; } | null; + /** + * Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). + */ + path?: string; +} +/** + * Workspace checkpoints in chronological order; empty when the workspace is not enabled. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesListCheckpointsResult". + */ +export interface WorkspacesListCheckpointsResult { + /** + * Workspace checkpoints in chronological order. Empty when workspace is not enabled. + */ + checkpoints: WorkspacesCheckpoints[]; } /** * Relative paths of files stored in the session workspace files directory. @@ -4169,6 +7695,30 @@ export interface WorkspacesListFilesResult { */ files: string[]; } +/** + * Checkpoint number to read. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesReadCheckpointRequest". + */ +export interface WorkspacesReadCheckpointRequest { + /** + * Checkpoint number to read + */ + number: number; +} +/** + * Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesReadCheckpointResult". + */ +export interface WorkspacesReadCheckpointResult { + /** + * Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing + */ + content: string | null; +} /** * Relative path of the workspace file to read. * @@ -4193,6 +7743,43 @@ export interface WorkspacesReadFileResult { */ content: string; } +/** + * Pasted content to save as a UTF-8 file in the session workspace. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesSaveLargePasteRequest". + */ +export interface WorkspacesSaveLargePasteRequest { + /** + * Pasted content to save as a UTF-8 file + */ + content: string; +} +/** + * Descriptor for the saved paste file, or null when the workspace is unavailable. + * + * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema + * via the `definition` "WorkspacesSaveLargePasteResult". + */ +export interface WorkspacesSaveLargePasteResult { + /** + * Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions) + */ + saved: { + /** + * Absolute filesystem path to the saved paste file + */ + filePath: string; + /** + * Filename within the workspace files directory + */ + filename: string; + /** + * Size of the saved file in bytes + */ + sizeBytes: number; + } | null; +} /** * Identifies the target session. * @@ -4214,7 +7801,7 @@ export function createServerRpc(connection: MessageConnection) { * * @param params Optional message to echo back to the caller. * - * @returns Server liveness response, including the echoed message, current timestamp, and protocol version. + * @returns Server liveness response, including the echoed message, current server timestamp, and protocol version. */ ping: async (params: PingRequest): Promise => connection.sendRequest("ping", params), @@ -4340,23 +7927,174 @@ export function createServerRpc(connection: MessageConnection) { /** @experimental */ sessions: { /** - * Creates a new session by forking persisted history from an existing session. + * Creates a new session by forking persisted history from an existing session. + * + * @param params Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. + * + * @returns Identifier and optional friendly name assigned to the newly forked session. + */ + fork: async (params: SessionsForkRequest): Promise => + connection.sendRequest("sessions.fork", params), + /** + * Connects to an existing remote session and exposes it as an SDK session. + * + * @param params Remote session connection parameters. + * + * @returns Remote session connection result. + */ + connect: async (params: ConnectRemoteSessionParams): Promise => + connection.sendRequest("sessions.connect", params), + /** + * Lists persisted sessions, optionally filtered by working-directory context. + * + * @param params Optional metadata-load limit and context filter applied to the returned sessions. + * + * @returns Persisted sessions matching the filter, ordered most-recently-modified first. + */ + list: async (params: SessionsListRequest): Promise => + connection.sendRequest("sessions.list", params), + /** + * Finds the local session bound to a GitHub task ID, if any. + * + * @param params GitHub task ID to look up. + * + * @returns ID of the local session bound to the given GitHub task, or omitted when none. + */ + findByTaskId: async (params: SessionsFindByTaskIDRequest): Promise => + connection.sendRequest("sessions.findByTaskId", params), + /** + * Resolves a UUID prefix to a unique session ID, if exactly one session matches. + * + * @param params UUID prefix to resolve to a unique session ID. + * + * @returns Session ID matching the prefix, omitted when no unique match exists. + */ + findByPrefix: async (params: SessionsFindByPrefixRequest): Promise => + connection.sendRequest("sessions.findByPrefix", params), + /** + * Returns the most-relevant prior session for a given working-directory context. + * + * @param params Optional working-directory context used to score session relevance. + * + * @returns Most-relevant session ID for the supplied context, or omitted when no sessions exist. + */ + getLastForContext: async (params: SessionsGetLastForContextRequest): Promise => + connection.sendRequest("sessions.getLastForContext", params), + /** + * Computes the absolute path to a session's persisted events.jsonl file. + * + * @param params Session ID whose event-log file path to compute. + * + * @returns Absolute path to the session's events.jsonl file on disk. + */ + getEventFilePath: async (params: SessionsGetEventFilePathRequest): Promise => + connection.sendRequest("sessions.getEventFilePath", params), + /** + * Returns the on-disk byte size of each session's workspace directory. + * + * @returns Map of sessionId -> on-disk size in bytes for each session's workspace directory. + */ + getSizes: async (): Promise => + connection.sendRequest("sessions.getSizes", {}), + /** + * Returns the subset of the supplied session IDs that are currently held by another running process. + * + * @param params Session IDs to test for live in-use locks. + * + * @returns Session IDs from the input set that are currently in use by another process. + */ + checkInUse: async (params: SessionsCheckInUseRequest): Promise => + connection.sendRequest("sessions.checkInUse", params), + /** + * Returns a session's persisted remote-steerable flag, if any has been recorded. + * + * @param params Session ID to look up the persisted remote-steerable flag for. + * + * @returns The session's persisted remote-steerable flag, or omitted when no value has been persisted. + */ + getPersistedRemoteSteerable: async (params: SessionsGetPersistedRemoteSteerableRequest): Promise => + connection.sendRequest("sessions.getPersistedRemoteSteerable", params), + /** + * Closes a session: emits shutdown, flushes pending events, releases the in-use lock, and disposes the active session. + * + * @param params Session ID to close. + * + * @returns Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. + */ + close: async (params: SessionsCloseRequest): Promise => + connection.sendRequest("sessions.close", params), + /** + * Closes, deactivates, and deletes a set of sessions, returning the bytes freed per session. + * + * @param params Session IDs to close, deactivate, and delete from disk. + * + * @returns Map of sessionId -> bytes freed by removing the session's workspace directory. + */ + bulkDelete: async (params: SessionsBulkDeleteRequest): Promise => + connection.sendRequest("sessions.bulkDelete", params), + /** + * Deletes sessions older than the given threshold, with optional dry-run and exclusion list. + * + * @param params Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true). + * + * @returns Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. + */ + pruneOld: async (params: SessionsPruneOldRequest): Promise => + connection.sendRequest("sessions.pruneOld", params), + /** + * Flushes a session's pending events to disk. + * + * @param params Session ID whose pending events should be flushed to disk. + * + * @returns Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). + */ + save: async (params: SessionsSaveRequest): Promise => + connection.sendRequest("sessions.save", params), + /** + * Releases the in-use lock held by this process for a session. + * + * @param params Session ID whose in-use lock should be released. + * + * @returns Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. + */ + releaseLock: async (params: SessionsReleaseLockRequest): Promise => + connection.sendRequest("sessions.releaseLock", params), + /** + * Backfills missing summary and context fields on the supplied session metadata records. + * + * @param params Session metadata records to enrich with summary and context information. + * + * @returns The same metadata records, with summary and context fields backfilled where available. + */ + enrichMetadata: async (params: SessionsEnrichMetadataRequest): Promise => + connection.sendRequest("sessions.enrichMetadata", params), + /** + * Reloads user, plugin, and (optionally) repo hooks on the active session. * - * @param params Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. + * @param params Active session ID and an optional flag for deferring repo-level hooks until folder trust. * - * @returns Identifier and optional friendly name assigned to the newly forked session. + * @returns Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. */ - fork: async (params: SessionsForkRequest): Promise => - connection.sendRequest("sessions.fork", params), + reloadPluginHooks: async (params: SessionsReloadPluginHooksRequest): Promise => + connection.sendRequest("sessions.reloadPluginHooks", params), /** - * Connects to an existing remote session and exposes it as an SDK session. + * Loads previously-deferred repo-level hooks on the active session, returning queued startup prompts. * - * @param params Remote session connection parameters. + * @param params Active session ID whose deferred repo-level hooks should be loaded. * - * @returns Remote session connection result. + * @returns Queued repo-level startup prompts and the total hook command count after loading. */ - connect: async (params: ConnectRemoteSessionParams): Promise => - connection.sendRequest("sessions.connect", params), + loadDeferredRepoHooks: async (params: SessionsLoadDeferredRepoHooksRequest): Promise => + connection.sendRequest("sessions.loadDeferredRepoHooks", params), + /** + * Replaces the manager-wide additional plugins registered with the session manager. + * + * @param params Manager-wide additional plugins to register; replaces any previously-configured set. + * + * @returns Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. + */ + setAdditionalPlugins: async (params: SessionsSetAdditionalPluginsRequest): Promise => + connection.sendRequest("sessions.setAdditionalPlugins", params), }, }; } @@ -4388,6 +8126,31 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ suspend: async (): Promise => connection.sendRequest("session.suspend", { sessionId }), + /** + * Sends a user message to the session and returns its message ID. + * + * @param params Parameters for sending a user message to the session + * + * @returns Result of sending a user message + */ + send: async (params: SendRequest): Promise => + connection.sendRequest("session.send", { sessionId, ...params }), + /** + * Aborts the current agent turn. + * + * @param params Parameters for aborting the current turn + * + * @returns Result of aborting the current turn + */ + abort: async (params: AbortRequest): Promise => + connection.sendRequest("session.abort", { sessionId, ...params }), + /** + * Shuts down the session and persists its final state. Awaits any deferred sessionEnd hooks before resolving so user-supplied hook scripts complete before the runtime tears down. + * + * @param params Parameters for shutting down the session + */ + shutdown: async (params: ShutdownRequest): Promise => + connection.sendRequest("session.shutdown", { sessionId, ...params }), auth: { /** * Gets authentication status and account metadata for the session. @@ -4396,12 +8159,21 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ getStatus: async (): Promise => connection.sendRequest("session.auth.getStatus", { sessionId }), + /** + * Updates the session's auth credentials used for outbound model and API requests. + * + * @param params New auth credentials to install on the session. Omit to leave credentials unchanged. + * + * @returns Indicates whether the credential update succeeded. + */ + setCredentials: async (params: SessionSetCredentialsParams): Promise => + connection.sendRequest("session.auth.setCredentials", { sessionId, ...params }), }, model: { /** * Gets the currently selected model for the session. * - * @returns The currently selected model for the session. + * @returns The currently selected model and reasoning effort for the session. */ getCurrent: async (): Promise => connection.sendRequest("session.model.getCurrent", { sessionId }), @@ -4414,6 +8186,15 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ switchTo: async (params: ModelSwitchToRequest): Promise => connection.sendRequest("session.model.switchTo", { sessionId, ...params }), + /** + * Updates the session's reasoning effort without changing the selected model. + * + * @param params Reasoning effort level to apply to the currently selected model. + * + * @returns Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. + */ + setReasoningEffort: async (params: ModelSetReasoningEffortRequest): Promise => + connection.sendRequest("session.model.setReasoningEffort", { sessionId, ...params }), }, mode: { /** @@ -4446,6 +8227,15 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ set: async (params: NameSetRequest): Promise => connection.sendRequest("session.name.set", { sessionId, ...params }), + /** + * Persists an auto-generated session summary as the session's name when no user-set name exists. + * + * @param params Auto-generated session summary to apply as the session's name when no user-set name exists. + * + * @returns Indicates whether the auto-generated summary was applied as the session's name. + */ + setAuto: async (params: NameSetAutoRequest): Promise => + connection.sendRequest("session.name.setAuto", { sessionId, ...params }), }, plan: { /** @@ -4472,7 +8262,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin /** * Gets current workspace metadata for the session. * - * @returns Current workspace metadata for the session, or null when not available. + * @returns Current workspace metadata for the session, including its absolute filesystem path when available. */ getWorkspace: async (): Promise => connection.sendRequest("session.workspaces.getWorkspace", { sessionId }), @@ -4499,6 +8289,31 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ createFile: async (params: WorkspacesCreateFileRequest): Promise => connection.sendRequest("session.workspaces.createFile", { sessionId, ...params }), + /** + * Lists workspace checkpoints in chronological order. + * + * @returns Workspace checkpoints in chronological order; empty when the workspace is not enabled. + */ + listCheckpoints: async (): Promise => + connection.sendRequest("session.workspaces.listCheckpoints", { sessionId }), + /** + * Reads the content of a workspace checkpoint by number. + * + * @param params Checkpoint number to read. + * + * @returns Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. + */ + readCheckpoint: async (params: WorkspacesReadCheckpointRequest): Promise => + connection.sendRequest("session.workspaces.readCheckpoint", { sessionId, ...params }), + /** + * Saves pasted content as a UTF-8 file in the session workspace. + * + * @param params Pasted content to save as a UTF-8 file in the session workspace. + * + * @returns Descriptor for the saved paste file, or null when the workspace is unavailable. + */ + saveLargePaste: async (params: WorkspacesSaveLargePasteRequest): Promise => + connection.sendRequest("session.workspaces.saveLargePaste", { sessionId, ...params }), }, instructions: { /** @@ -4577,6 +8392,36 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ list: async (): Promise => connection.sendRequest("session.tasks.list", { sessionId }), + /** + * Refreshes metadata for any detached background shells the runtime knows about. + * + * @returns Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. + */ + refresh: async (): Promise => + connection.sendRequest("session.tasks.refresh", { sessionId }), + /** + * Waits for all in-flight background tasks and any follow-up turns to settle. + * + * @returns Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). + */ + waitForPending: async (): Promise => + connection.sendRequest("session.tasks.waitForPending", { sessionId }), + /** + * Returns progress information for a background task by ID. + * + * @param params Identifier of the background task to fetch progress for. + * + * @returns Progress information for the task, or null when no task with that ID is tracked. + */ + getProgress: async (params: TasksGetProgressRequest): Promise => + connection.sendRequest("session.tasks.getProgress", { sessionId, ...params }), + /** + * Returns the first sync-waiting task that can currently be promoted to background mode. + * + * @returns The first sync-waiting task that can currently be promoted to background mode. + */ + getCurrentPromotable: async (): Promise => + connection.sendRequest("session.tasks.getCurrentPromotable", { sessionId }), /** * Promotes an eligible synchronously-waited task so it continues running in the background. * @@ -4586,6 +8431,13 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ promoteToBackground: async (params: TasksPromoteToBackgroundRequest): Promise => connection.sendRequest("session.tasks.promoteToBackground", { sessionId, ...params }), + /** + * Atomically promotes the first promotable sync-waiting task to background mode and returns it. + * + * @returns The promoted task as it now exists in background mode, omitted if no promotable task was waiting. + */ + promoteCurrentToBackground: async (): Promise => + connection.sendRequest("session.tasks.promoteCurrentToBackground", { sessionId }), /** * Cancels a background task. * @@ -4623,6 +8475,13 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ list: async (): Promise => connection.sendRequest("session.skills.list", { sessionId }), + /** + * Returns the skills that have been invoked during this session. + * + * @returns Skills invoked during this session, ordered by invocation time (most recent last). + */ + getInvoked: async (): Promise => + connection.sendRequest("session.skills.getInvoked", { sessionId }), /** * Enables a skill for the session. * @@ -4644,6 +8503,11 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ reload: async (): Promise => connection.sendRequest("session.skills.reload", { sessionId }), + /** + * Ensures the session's skill definitions have been loaded from disk. + */ + ensureLoaded: async (): Promise => + connection.sendRequest("session.skills.ensureLoaded", { sessionId }), }, /** @experimental */ mcp: { @@ -4673,6 +8537,40 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ reload: async (): Promise => connection.sendRequest("session.mcp.reload", { sessionId }), + /** + * Runs an MCP sampling inference on behalf of an MCP server. + * + * @param params Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. + * + * @returns Outcome of an MCP sampling execution: success result, failure error, or cancellation. + */ + executeSampling: async (params: McpExecuteSamplingParams): Promise => + connection.sendRequest("session.mcp.executeSampling", { sessionId, ...params }), + /** + * Cancels an in-flight MCP sampling execution by request ID. + * + * @param params The requestId previously passed to executeSampling that should be cancelled. + * + * @returns Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. + */ + cancelSamplingExecution: async (params: McpCancelSamplingExecutionParams): Promise => + connection.sendRequest("session.mcp.cancelSamplingExecution", { sessionId, ...params }), + /** + * Sets how environment-variable values supplied to MCP servers are resolved (direct or indirect). + * + * @param params Mode controlling how MCP server env values are resolved (`direct` or `indirect`). + * + * @returns Env-value mode recorded on the session after the update. + */ + setEnvValueMode: async (params: McpSetEnvValueModeParams): Promise => + connection.sendRequest("session.mcp.setEnvValueMode", { sessionId, ...params }), + /** + * Removes the auto-managed `github` MCP server when present. + * + * @returns Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). + */ + removeGitHub: async (): Promise => + connection.sendRequest("session.mcp.removeGitHub", { sessionId }), /** @experimental */ oauth: { /** @@ -4697,6 +8595,28 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin connection.sendRequest("session.plugins.list", { sessionId }), }, /** @experimental */ + options: { + /** + * Patches the genuinely-mutable subset of session options. + * + * @param params Patch of mutable session options to apply to the running session. + * + * @returns Indicates whether the session options patch was applied successfully. + */ + update: async (params: SessionUpdateOptionsParams): Promise => + connection.sendRequest("session.options.update", { sessionId, ...params }), + }, + /** @experimental */ + lsp: { + /** + * Loads the merged LSP configuration set for the session's working directory. + * + * @param params Parameters for (re)loading the merged LSP configuration set. + */ + initialize: async (params: LspInitializeRequest): Promise => + connection.sendRequest("session.lsp.initialize", { sessionId, ...params }), + }, + /** @experimental */ extensions: { /** * Lists extensions discovered for the session and their current status. @@ -4735,6 +8655,13 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ handlePendingToolCall: async (params: HandlePendingToolCallRequest): Promise => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params }), + /** + * Resolves, builds, and validates the runtime tool list for the session. + * + * @returns Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. + */ + initializeAndValidate: async (): Promise => + connection.sendRequest("session.tools.initializeAndValidate", { sessionId }), }, commands: { /** @@ -4765,15 +8692,43 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin handlePendingCommand: async (params: CommandsHandlePendingCommandRequest): Promise => connection.sendRequest("session.commands.handlePendingCommand", { sessionId, ...params }), /** - * Responds to a queued command request from the session. + * Executes a slash command synchronously and returns any error. + * + * @param params Slash command name and argument string to execute synchronously. + * + * @returns Error message produced while executing the command, if any. + */ + execute: async (params: ExecuteCommandParams): Promise => + connection.sendRequest("session.commands.execute", { sessionId, ...params }), + /** + * Enqueues a slash command for FIFO processing on the local session. + * + * @param params Slash-prefixed command string to enqueue for FIFO processing. + * + * @returns Indicates whether the command was accepted into the local execution queue. + */ + enqueue: async (params: EnqueueCommandParams): Promise => + connection.sendRequest("session.commands.enqueue", { sessionId, ...params }), + /** + * Reports whether the host actually executed a queued command and whether to continue processing. * - * @param params Queued command request ID and the result indicating whether the client handled it. + * @param params Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). * - * @returns Indicates whether the queued-command response was accepted by the session. + * @returns Indicates whether the queued-command response was matched to a pending request. */ respondToQueuedCommand: async (params: CommandsRespondToQueuedCommandRequest): Promise => connection.sendRequest("session.commands.respondToQueuedCommand", { sessionId, ...params }), }, + /** @experimental */ + telemetry: { + /** + * Sets feature override key/value pairs to attach to subsequent telemetry events for the session. + * + * @param params Feature override key/value pairs to attach to subsequent telemetry events from this session. + */ + setFeatureOverrides: async (params: TelemetrySetFeatureOverridesRequest): Promise => + connection.sendRequest("session.telemetry.setFeatureOverrides", { sessionId, ...params }), + }, ui: { /** * Requests structured input from a UI-capable client. @@ -4793,8 +8748,69 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ handlePendingElicitation: async (params: UIHandlePendingElicitationRequest): Promise => connection.sendRequest("session.ui.handlePendingElicitation", { sessionId, ...params }), + /** + * Resolves a pending `user_input.requested` event with the user's response. + * + * @param params Request ID of a pending `user_input.requested` event and the user's response. + * + * @returns Indicates whether the pending UI request was resolved by this call. + */ + handlePendingUserInput: async (params: UIHandlePendingUserInputRequest): Promise => + connection.sendRequest("session.ui.handlePendingUserInput", { sessionId, ...params }), + /** + * Resolves a pending `sampling.requested` event with a sampling result, or rejects it. + * + * @param params Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). + * + * @returns Indicates whether the pending UI request was resolved by this call. + */ + handlePendingSampling: async (params: UIHandlePendingSamplingRequest): Promise => + connection.sendRequest("session.ui.handlePendingSampling", { sessionId, ...params }), + /** + * Resolves a pending `auto_mode_switch.requested` event with the user's accept/decline decision. + * + * @param params Request ID of a pending `auto_mode_switch.requested` event and the user's response. + * + * @returns Indicates whether the pending UI request was resolved by this call. + */ + handlePendingAutoModeSwitch: async (params: UIHandlePendingAutoModeSwitchRequest): Promise => + connection.sendRequest("session.ui.handlePendingAutoModeSwitch", { sessionId, ...params }), + /** + * Resolves a pending `exit_plan_mode.requested` event with the user's response. + * + * @param params Request ID of a pending `exit_plan_mode.requested` event and the user's response. + * + * @returns Indicates whether the pending UI request was resolved by this call. + */ + handlePendingExitPlanMode: async (params: UIHandlePendingExitPlanModeRequest): Promise => + connection.sendRequest("session.ui.handlePendingExitPlanMode", { sessionId, ...params }), + /** + * Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch. + * + * @returns Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). + */ + registerDirectAutoModeSwitchHandler: async (): Promise => + connection.sendRequest("session.ui.registerDirectAutoModeSwitchHandler", { sessionId }), + /** + * Unregisters a previously-registered in-process auto-mode-switch handler by its opaque handle. + * + * @param params Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. + * + * @returns Indicates whether the handle was active and the registration count was decremented. + */ + unregisterDirectAutoModeSwitchHandler: async (params: UIUnregisterDirectAutoModeSwitchHandlerRequest): Promise => + connection.sendRequest("session.ui.unregisterDirectAutoModeSwitchHandler", { sessionId, ...params }), }, permissions: { + /** + * Replaces selected permission policy fields (rules, paths, URLs, exclusions, allow-all flags) on the session. + * + * @param params Patch of permission policy fields to apply (omit a field to leave it unchanged). + * + * @returns Indicates whether the operation succeeded. + */ + configure: async (params: PermissionsConfigureParams): Promise => + connection.sendRequest("session.permissions.configure", { sessionId, ...params }), /** * Provides a decision for a pending tool permission request. * @@ -4804,15 +8820,40 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ handlePendingPermissionRequest: async (params: PermissionDecisionRequest): Promise => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params }), + /** + * Reconstructs the set of pending tool permission requests from the session's event history. + * + * @returns List of pending permission requests reconstructed from event history. + */ + pendingRequests: async (): Promise => + connection.sendRequest("session.permissions.pendingRequests", { sessionId }), /** * Enables or disables automatic approval of tool permission requests for the session. * - * @param params Whether to auto-approve all tool permission requests for the rest of the session. + * @param params Allow-all toggle for tool permission requests, with an optional telemetry source. * * @returns Indicates whether the operation succeeded. */ setApproveAll: async (params: PermissionsSetApproveAllRequest): Promise => connection.sendRequest("session.permissions.setApproveAll", { sessionId, ...params }), + /** + * Adds or removes session-scoped or location-scoped permission rules. + * + * @param params Scope and add/remove instructions for modifying session- or location-scoped permission rules. + * + * @returns Indicates whether the operation succeeded. + */ + modifyRules: async (params: PermissionsModifyRulesParams): Promise => + connection.sendRequest("session.permissions.modifyRules", { sessionId, ...params }), + /** + * Sets whether the client wants permission prompts bridged into session events. + * + * @param params Toggles whether permission prompts should be bridged into session events for this client. + * + * @returns Indicates whether the operation succeeded. + */ + setRequired: async (params: PermissionsSetRequiredRequest): Promise => + connection.sendRequest("session.permissions.setRequired", { sessionId, ...params }), /** * Clears session-scoped tool permission approvals. * @@ -4820,16 +8861,134 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ resetSessionApprovals: async (): Promise => connection.sendRequest("session.permissions.resetSessionApprovals", { sessionId }), + /** + * Notifies the runtime that a permission prompt UI has been shown to the user. + * + * @param params Notification payload describing the permission prompt that the client just rendered. + * + * @returns Indicates whether the operation succeeded. + */ + notifyPromptShown: async (params: PermissionPromptShownNotification): Promise => + connection.sendRequest("session.permissions.notifyPromptShown", { sessionId, ...params }), + paths: { + /** + * Returns the session's allowed directories and primary working directory. + * + * @returns Snapshot of the session's allow-listed directories and primary working directory. + */ + list: async (): Promise => + connection.sendRequest("session.permissions.paths.list", { sessionId }), + /** + * Adds a directory to the session's allow-list. + * + * @param params Directory path to add to the session's allowed directories. + * + * @returns Indicates whether the operation succeeded. + */ + add: async (params: PermissionPathsAddParams): Promise => + connection.sendRequest("session.permissions.paths.add", { sessionId, ...params }), + /** + * Updates the session's primary working directory used by the permission policy. + * + * @param params Directory path to set as the session's new primary working directory. + * + * @returns Indicates whether the operation succeeded. + */ + updatePrimary: async (params: PermissionPathsUpdatePrimaryParams): Promise => + connection.sendRequest("session.permissions.paths.updatePrimary", { sessionId, ...params }), + /** + * Reports whether a path falls within any of the session's allowed directories. + * + * @param params Path to evaluate against the session's allowed directories. + * + * @returns Indicates whether the supplied path is within the session's allowed directories. + */ + isPathWithinAllowedDirectories: async (params: PermissionPathsAllowedCheckParams): Promise => + connection.sendRequest("session.permissions.paths.isPathWithinAllowedDirectories", { sessionId, ...params }), + /** + * Reports whether a path falls within the session's workspace (primary) directory. + * + * @param params Path to evaluate against the session's workspace (primary) directory. + * + * @returns Indicates whether the supplied path is within the session's workspace directory. + */ + isPathWithinWorkspace: async (params: PermissionPathsWorkspaceCheckParams): Promise => + connection.sendRequest("session.permissions.paths.isPathWithinWorkspace", { sessionId, ...params }), + }, + urls: { + /** + * Toggles the runtime's URL-permission policy between unrestricted and restricted modes. + * + * @param params Whether the URL-permission policy should run in unrestricted mode. + * + * @returns Indicates whether the operation succeeded. + */ + setUnrestrictedMode: async (params: PermissionUrlsSetUnrestrictedModeParams): Promise => + connection.sendRequest("session.permissions.urls.setUnrestrictedMode", { sessionId, ...params }), + }, }, /** * Emits a user-visible session log event. * - * @param params Message text, optional severity level, persistence flag, and optional follow-up URL. + * @param params Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. * * @returns Identifier of the session event that was emitted for the log message. */ log: async (params: LogRequest): Promise => connection.sendRequest("session.log", { sessionId, ...params }), + /** @experimental */ + metadata: { + /** + * Returns a snapshot of the session's identifying metadata, mode, agent, and remote info. + * + * @returns Point-in-time snapshot of slow-changing session identifier and state fields + */ + snapshot: async (): Promise => + connection.sendRequest("session.metadata.snapshot", { sessionId }), + /** + * Reports whether the local session is currently processing user/agent messages. + * + * @returns Indicates whether the local session is currently processing a turn or background continuation. + */ + isProcessing: async (): Promise => + connection.sendRequest("session.metadata.isProcessing", { sessionId }), + /** + * Returns the token breakdown for the session's current context window for a given model. + * + * @param params Model identifier and token limits used to compute the context-info breakdown. + * + * @returns Token breakdown for the session's current context window, or null if uninitialized. + */ + contextInfo: async (params: MetadataContextInfoRequest): Promise => + connection.sendRequest("session.metadata.contextInfo", { sessionId, ...params }), + /** + * Records a working-directory/git context change and emits a `session.context_changed` event. + * + * @param params Updated working-directory/git context to record on the session. + * + * @returns Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). + */ + recordContextChange: async (params: MetadataRecordContextChangeRequest): Promise => + connection.sendRequest("session.metadata.recordContextChange", { sessionId, ...params }), + /** + * Updates the session's recorded working directory. + * + * @param params Absolute path to set as the session's new working directory. + * + * @returns Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. + */ + setWorkingDirectory: async (params: MetadataSetWorkingDirectoryRequest): Promise => + connection.sendRequest("session.metadata.setWorkingDirectory", { sessionId, ...params }), + /** + * Re-tokenizes the session's existing messages against a model and returns aggregate token totals. + * + * @param params Model identifier to use when re-tokenizing the session's existing messages. + * + * @returns Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. + */ + recomputeContextTokens: async (params: MetadataRecomputeContextTokensRequest): Promise => + connection.sendRequest("session.metadata.recomputeContextTokens", { sessionId, ...params }), + }, shell: { /** * Starts a shell command and streams output through session notifications. @@ -4855,7 +9014,7 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin /** * Compacts the session history to reduce context usage. * - * @returns Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. + * @returns Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. */ compact: async (): Promise => connection.sendRequest("session.history.compact", { sessionId }), @@ -4868,6 +9027,86 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ truncate: async (params: HistoryTruncateRequest): Promise => connection.sendRequest("session.history.truncate", { sessionId, ...params }), + /** + * Cancels any in-progress background compaction on a local session. + * + * @returns Indicates whether an in-progress background compaction was cancelled. + */ + cancelBackgroundCompaction: async (): Promise => + connection.sendRequest("session.history.cancelBackgroundCompaction", { sessionId }), + /** + * Aborts any in-progress manual compaction on a local session. + * + * @returns Indicates whether an in-progress manual compaction was aborted. + */ + abortManualCompaction: async (): Promise => + connection.sendRequest("session.history.abortManualCompaction", { sessionId }), + /** + * Produces a markdown summary of the session's conversation context for hand-off scenarios. + * + * @returns Markdown summary of the conversation context (empty when not available). + */ + summarizeForHandoff: async (): Promise => + connection.sendRequest("session.history.summarizeForHandoff", { sessionId }), + }, + /** @experimental */ + queue: { + /** + * Returns the local session's pending user-facing queued items and steering messages. + * + * @returns Snapshot of the session's pending queued items and immediate-steering messages. + */ + pendingItems: async (): Promise => + connection.sendRequest("session.queue.pendingItems", { sessionId }), + /** + * Removes the most recently queued user-facing item (LIFO). + * + * @returns Indicates whether a user-facing pending item was removed. + */ + removeMostRecent: async (): Promise => + connection.sendRequest("session.queue.removeMostRecent", { sessionId }), + /** + * Clears all pending queued items on the local session. + */ + clear: async (): Promise => + connection.sendRequest("session.queue.clear", { sessionId }), + }, + /** @experimental */ + eventLog: { + /** + * Reads a batch of session events from a cursor, optionally waiting for new events. + * + * @param params Cursor, batch size, and optional long-poll/filter parameters for reading session events. + * + * @returns Batch of session events returned by a read, with cursor and continuation metadata. + */ + read: async (params: EventLogReadRequest): Promise => + connection.sendRequest("session.eventLog.read", { sessionId, ...params }), + /** + * Returns a snapshot of the current tail cursor without consuming events. + * + * @returns Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). + */ + tail: async (): Promise => + connection.sendRequest("session.eventLog.tail", { sessionId }), + /** + * Registers consumer interest in an event type for runtime gating purposes. + * + * @param params Event type to register consumer interest for, used by runtime gating logic. + * + * @returns Opaque handle representing an event-type interest registration. + */ + registerInterest: async (params: RegisterEventInterestParams): Promise => + connection.sendRequest("session.eventLog.registerInterest", { sessionId, ...params }), + /** + * Releases a consumer's previously-registered interest in an event type. + * + * @param params Opaque handle previously returned by `registerInterest` to release. + * + * @returns Indicates whether the operation succeeded. + */ + releaseInterest: async (params: ReleaseEventInterestParams): Promise => + connection.sendRequest("session.eventLog.releaseInterest", { sessionId, ...params }), }, /** @experimental */ usage: { @@ -4895,6 +9134,34 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin */ disable: async (): Promise => connection.sendRequest("session.remote.disable", { sessionId }), + /** + * Persists a remote-steerability change emitted by the host as a session event. + * + * @param params New remote-steerability state to persist as a `session.remote_steerable_changed` event. + * + * @returns Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. + */ + notifySteerableChanged: async (params: RemoteNotifySteerableChangedRequest): Promise => + connection.sendRequest("session.remote.notifySteerableChanged", { sessionId, ...params }), + }, + /** @experimental */ + schedule: { + /** + * Lists the session's currently active scheduled prompts. + * + * @returns Snapshot of the currently active recurring prompts for this session. + */ + list: async (): Promise => + connection.sendRequest("session.schedule.list", { sessionId }), + /** + * Removes a scheduled prompt by id. + * + * @param params Identifier of the scheduled prompt to remove. + * + * @returns Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. + */ + stop: async (params: ScheduleStopRequest): Promise => + connection.sendRequest("session.schedule.stop", { sessionId, ...params }), }, }; } diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts index 64c9e10ba..f72c2dbb0 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -1791,7 +1791,7 @@ export interface UserMessageData { */ isAutopilotContinuation?: boolean; /** - * Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit + * Path-backed native document attachments that stayed on the tagged_files path flow because native upload could not read them or would exceed the request size limit */ nativeDocumentPathFallbackPaths?: string[]; /** @@ -2623,7 +2623,7 @@ export interface AssistantUsageQuotaSnapshot { */ overageAllowedWithExhaustedQuota: boolean; /** - * Percentage of quota remaining (0.0 to 1.0) + * Percentage of quota remaining (0 to 100) */ remainingPercentage: number; /** @@ -4721,7 +4721,7 @@ export interface PermissionDeniedByRules { */ export interface PermissionRule { /** - * Optional rule argument matched against the request + * Argument value matched against the request, or null when the rule kind has no argument (e.g. 'read', 'write', 'memory'). */ argument: string | null; /** diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index 50b1f8105..c821c042a 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING -from .session_events import EmbeddedBlobResourceContents, EmbeddedTextResourceContents, McpServerSource, McpServerStatus, ReasoningSummary, SessionMode, SkillSource +from .session_events import AbortReason, EmbeddedBlobResourceContents, EmbeddedTextResourceContents, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, ReasoningSummary, SessionEvent, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval if TYPE_CHECKING: from .._jsonrpc import JsonRpcClient @@ -39,14 +39,18 @@ def from_union(fs, x): pass assert False -def from_int(x: Any) -> int: - assert isinstance(x, int) and not isinstance(x, bool) - return 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_int(x: Any) -> int: + assert isinstance(x, int) and not isinstance(x, bool) + return x + def from_float(x: Any) -> float: assert isinstance(x, (float, int)) and not isinstance(x, bool) return float(x) @@ -59,10 +63,6 @@ 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_class(c: type[T], x: Any) -> dict: - assert isinstance(x, c) - return cast(Any, x).to_dict() - def from_list(f: Callable[[Any], T], x: Any) -> list[T]: assert isinstance(x, list) return [f(y) for y in x] @@ -74,6 +74,49 @@ def to_enum(c: type[EnumT], x: Any) -> EnumT: def from_datetime(x: Any) -> datetime: return dateutil.parser.parse(x) +@dataclass +class AbortRequest: + """Parameters for aborting the current turn""" + + reason: AbortReason | None = None + """Finite reason code describing why the current turn was aborted""" + + @staticmethod + def from_dict(obj: Any) -> 'AbortRequest': + assert isinstance(obj, dict) + reason = from_union([AbortReason, from_none], obj.get("reason")) + return AbortRequest(reason) + + def to_dict(self) -> dict: + result: dict = {} + if self.reason is not None: + result["reason"] = from_union([lambda x: to_enum(AbortReason, x), from_none], self.reason) + return result + +@dataclass +class AbortResult: + """Result of aborting the current turn""" + + success: bool + """Whether the abort completed successfully""" + + error: str | None = None + """Error message if the abort failed""" + + @staticmethod + def from_dict(obj: Any) -> 'AbortResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + error = from_union([from_str, from_none], obj.get("error")) + return AbortResult(success, error) + + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + if self.error is not None: + result["error"] = from_union([from_str, from_none], self.error) + return result + @dataclass class AccountGetQuotaRequest: git_hub_token: str | None = None @@ -148,63 +191,68 @@ def to_dict(self) -> dict: return result # Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class AgentInfo: - """Schema for the `AgentInfo` type. +class AgentInfoSource(Enum): + """Where the agent definition was loaded from""" - The newly selected custom agent - """ - description: str - """Description of the agent's purpose""" + BUILTIN = "builtin" + INHERITED = "inherited" + PLUGIN = "plugin" + PROJECT = "project" + REMOTE = "remote" + USER = "user" - display_name: str - """Human-readable display name""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AgentSelectRequest: + """Name of the custom agent to select for subsequent turns.""" name: str - """Unique identifier of the custom agent""" - - path: str | None = None - """Absolute local file path of the agent definition. Only set for file-based agents loaded - from disk; remote agents do not have a path. - """ + """Name of the custom agent to select""" @staticmethod - def from_dict(obj: Any) -> 'AgentInfo': + def from_dict(obj: Any) -> 'AgentSelectRequest': assert isinstance(obj, dict) - description = from_str(obj.get("description")) - display_name = from_str(obj.get("displayName")) name = from_str(obj.get("name")) - path = from_union([from_str, from_none], obj.get("path")) - return AgentInfo(description, display_name, name, path) + return AgentSelectRequest(name) def to_dict(self) -> dict: result: dict = {} - result["description"] = from_str(self.description) - result["displayName"] = from_str(self.display_name) result["name"] = from_str(self.name) - if self.path is not None: - 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 AgentSelectRequest: - """Name of the custom agent to select for subsequent turns.""" +class CopilotUserResponseEndpoints: + """Schema for the `CopilotUserResponseEndpoints` type.""" - name: str - """Name of the custom agent to select""" + api: str | None = None + origin_tracker: str | None = None + proxy: str | None = None + telemetry: str | None = None @staticmethod - def from_dict(obj: Any) -> 'AgentSelectRequest': + def from_dict(obj: Any) -> 'CopilotUserResponseEndpoints': assert isinstance(obj, dict) - name = from_str(obj.get("name")) - return AgentSelectRequest(name) + api = from_union([from_str, from_none], obj.get("api")) + origin_tracker = from_union([from_str, from_none], obj.get("origin-tracker")) + proxy = from_union([from_str, from_none], obj.get("proxy")) + telemetry = from_union([from_str, from_none], obj.get("telemetry")) + return CopilotUserResponseEndpoints(api, origin_tracker, proxy, telemetry) def to_dict(self) -> dict: result: dict = {} - result["name"] = from_str(self.name) + if self.api is not None: + result["api"] = from_union([from_str, from_none], self.api) + if self.origin_tracker is not None: + result["origin-tracker"] = from_union([from_str, from_none], self.origin_tracker) + if self.proxy is not None: + result["proxy"] = from_union([from_str, from_none], self.proxy) + if self.telemetry is not None: + result["telemetry"] = from_union([from_str, from_none], self.telemetry) return result +class APIKeyAuthInfoType(Enum): + API_KEY = "api-key" + class AuthInfoType(Enum): """Authentication type""" @@ -328,11 +376,11 @@ def to_dict(self) -> dict: @dataclass class CommandsRespondToQueuedCommandResult: - """Indicates whether the queued-command response was accepted by the session.""" + """Indicates whether the queued-command response was matched to a pending request.""" success: bool - """Whether the response was accepted (false if the requestId was not found or already - resolved) + """Whether a pending queued command with the given request ID was found and resolved. False + when the request was already resolved, cancelled, or unknown. """ @staticmethod @@ -459,23 +507,224 @@ class ContentFilterMode(Enum): MARKDOWN = "markdown" NONE = "none" +class Host(Enum): + HTTPS_GITHUB_COM = "https://github.com" + +class CopilotAPITokenAuthInfoType(Enum): + COPILOT_API_TOKEN = "copilot-api-token" + +@dataclass +class CopilotUserResponseQuotaSnapshotsChat: + """Schema for the `CopilotUserResponseQuotaSnapshotsChat` type.""" + + entitlement: float | None = None + has_quota: bool | None = None + overage_count: float | None = None + overage_permitted: bool | None = None + percent_remaining: float | None = None + quota_id: str | None = None + quota_remaining: float | None = None + quota_reset_at: float | None = None + remaining: float | None = None + timestamp_utc: str | None = None + token_based_billing: bool | None = None + unlimited: bool | None = None + + @staticmethod + def from_dict(obj: Any) -> 'CopilotUserResponseQuotaSnapshotsChat': + assert isinstance(obj, dict) + entitlement = from_union([from_float, from_none], obj.get("entitlement")) + has_quota = from_union([from_bool, from_none], obj.get("has_quota")) + overage_count = from_union([from_float, from_none], obj.get("overage_count")) + overage_permitted = from_union([from_bool, from_none], obj.get("overage_permitted")) + percent_remaining = from_union([from_float, from_none], obj.get("percent_remaining")) + quota_id = from_union([from_str, from_none], obj.get("quota_id")) + quota_remaining = from_union([from_float, from_none], obj.get("quota_remaining")) + quota_reset_at = from_union([from_float, from_none], obj.get("quota_reset_at")) + remaining = from_union([from_float, from_none], obj.get("remaining")) + timestamp_utc = from_union([from_str, from_none], obj.get("timestamp_utc")) + token_based_billing = from_union([from_bool, from_none], obj.get("token_based_billing")) + unlimited = from_union([from_bool, from_none], obj.get("unlimited")) + return CopilotUserResponseQuotaSnapshotsChat(entitlement, has_quota, overage_count, overage_permitted, percent_remaining, quota_id, quota_remaining, quota_reset_at, remaining, timestamp_utc, token_based_billing, unlimited) + + def to_dict(self) -> dict: + result: dict = {} + if self.entitlement is not None: + result["entitlement"] = from_union([to_float, from_none], self.entitlement) + if self.has_quota is not None: + result["has_quota"] = from_union([from_bool, from_none], self.has_quota) + if self.overage_count is not None: + result["overage_count"] = from_union([to_float, from_none], self.overage_count) + if self.overage_permitted is not None: + result["overage_permitted"] = from_union([from_bool, from_none], self.overage_permitted) + if self.percent_remaining is not None: + result["percent_remaining"] = from_union([to_float, from_none], self.percent_remaining) + if self.quota_id is not None: + result["quota_id"] = from_union([from_str, from_none], self.quota_id) + if self.quota_remaining is not None: + result["quota_remaining"] = from_union([to_float, from_none], self.quota_remaining) + if self.quota_reset_at is not None: + result["quota_reset_at"] = from_union([to_float, from_none], self.quota_reset_at) + if self.remaining is not None: + result["remaining"] = from_union([to_float, from_none], self.remaining) + if self.timestamp_utc is not None: + result["timestamp_utc"] = from_union([from_str, from_none], self.timestamp_utc) + if self.token_based_billing is not None: + result["token_based_billing"] = from_union([from_bool, from_none], self.token_based_billing) + if self.unlimited is not None: + result["unlimited"] = from_union([from_bool, from_none], self.unlimited) + return result + +@dataclass +class CopilotUserResponseQuotaSnapshotsCompletions: + """Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type.""" + + entitlement: float | None = None + has_quota: bool | None = None + overage_count: float | None = None + overage_permitted: bool | None = None + percent_remaining: float | None = None + quota_id: str | None = None + quota_remaining: float | None = None + quota_reset_at: float | None = None + remaining: float | None = None + timestamp_utc: str | None = None + token_based_billing: bool | None = None + unlimited: bool | None = None + + @staticmethod + def from_dict(obj: Any) -> 'CopilotUserResponseQuotaSnapshotsCompletions': + assert isinstance(obj, dict) + entitlement = from_union([from_float, from_none], obj.get("entitlement")) + has_quota = from_union([from_bool, from_none], obj.get("has_quota")) + overage_count = from_union([from_float, from_none], obj.get("overage_count")) + overage_permitted = from_union([from_bool, from_none], obj.get("overage_permitted")) + percent_remaining = from_union([from_float, from_none], obj.get("percent_remaining")) + quota_id = from_union([from_str, from_none], obj.get("quota_id")) + quota_remaining = from_union([from_float, from_none], obj.get("quota_remaining")) + quota_reset_at = from_union([from_float, from_none], obj.get("quota_reset_at")) + remaining = from_union([from_float, from_none], obj.get("remaining")) + timestamp_utc = from_union([from_str, from_none], obj.get("timestamp_utc")) + token_based_billing = from_union([from_bool, from_none], obj.get("token_based_billing")) + unlimited = from_union([from_bool, from_none], obj.get("unlimited")) + return CopilotUserResponseQuotaSnapshotsCompletions(entitlement, has_quota, overage_count, overage_permitted, percent_remaining, quota_id, quota_remaining, quota_reset_at, remaining, timestamp_utc, token_based_billing, unlimited) + + def to_dict(self) -> dict: + result: dict = {} + if self.entitlement is not None: + result["entitlement"] = from_union([to_float, from_none], self.entitlement) + if self.has_quota is not None: + result["has_quota"] = from_union([from_bool, from_none], self.has_quota) + if self.overage_count is not None: + result["overage_count"] = from_union([to_float, from_none], self.overage_count) + if self.overage_permitted is not None: + result["overage_permitted"] = from_union([from_bool, from_none], self.overage_permitted) + if self.percent_remaining is not None: + result["percent_remaining"] = from_union([to_float, from_none], self.percent_remaining) + if self.quota_id is not None: + result["quota_id"] = from_union([from_str, from_none], self.quota_id) + if self.quota_remaining is not None: + result["quota_remaining"] = from_union([to_float, from_none], self.quota_remaining) + if self.quota_reset_at is not None: + result["quota_reset_at"] = from_union([to_float, from_none], self.quota_reset_at) + if self.remaining is not None: + result["remaining"] = from_union([to_float, from_none], self.remaining) + if self.timestamp_utc is not None: + result["timestamp_utc"] = from_union([from_str, from_none], self.timestamp_utc) + if self.token_based_billing is not None: + result["token_based_billing"] = from_union([from_bool, from_none], self.token_based_billing) + if self.unlimited is not None: + result["unlimited"] = from_union([from_bool, from_none], self.unlimited) + return result + +@dataclass +class CopilotUserResponseQuotaSnapshotsPremiumInteractions: + """Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type.""" + + entitlement: float | None = None + has_quota: bool | None = None + overage_count: float | None = None + overage_permitted: bool | None = None + percent_remaining: float | None = None + quota_id: str | None = None + quota_remaining: float | None = None + quota_reset_at: float | None = None + remaining: float | None = None + timestamp_utc: str | None = None + token_based_billing: bool | None = None + unlimited: bool | None = None + + @staticmethod + def from_dict(obj: Any) -> 'CopilotUserResponseQuotaSnapshotsPremiumInteractions': + assert isinstance(obj, dict) + entitlement = from_union([from_float, from_none], obj.get("entitlement")) + has_quota = from_union([from_bool, from_none], obj.get("has_quota")) + overage_count = from_union([from_float, from_none], obj.get("overage_count")) + overage_permitted = from_union([from_bool, from_none], obj.get("overage_permitted")) + percent_remaining = from_union([from_float, from_none], obj.get("percent_remaining")) + quota_id = from_union([from_str, from_none], obj.get("quota_id")) + quota_remaining = from_union([from_float, from_none], obj.get("quota_remaining")) + quota_reset_at = from_union([from_float, from_none], obj.get("quota_reset_at")) + remaining = from_union([from_float, from_none], obj.get("remaining")) + timestamp_utc = from_union([from_str, from_none], obj.get("timestamp_utc")) + token_based_billing = from_union([from_bool, from_none], obj.get("token_based_billing")) + unlimited = from_union([from_bool, from_none], obj.get("unlimited")) + return CopilotUserResponseQuotaSnapshotsPremiumInteractions(entitlement, has_quota, overage_count, overage_permitted, percent_remaining, quota_id, quota_remaining, quota_reset_at, remaining, timestamp_utc, token_based_billing, unlimited) + + def to_dict(self) -> dict: + result: dict = {} + if self.entitlement is not None: + result["entitlement"] = from_union([to_float, from_none], self.entitlement) + if self.has_quota is not None: + result["has_quota"] = from_union([from_bool, from_none], self.has_quota) + if self.overage_count is not None: + result["overage_count"] = from_union([to_float, from_none], self.overage_count) + if self.overage_permitted is not None: + result["overage_permitted"] = from_union([from_bool, from_none], self.overage_permitted) + if self.percent_remaining is not None: + result["percent_remaining"] = from_union([to_float, from_none], self.percent_remaining) + if self.quota_id is not None: + result["quota_id"] = from_union([from_str, from_none], self.quota_id) + if self.quota_remaining is not None: + result["quota_remaining"] = from_union([to_float, from_none], self.quota_remaining) + if self.quota_reset_at is not None: + result["quota_reset_at"] = from_union([to_float, from_none], self.quota_reset_at) + if self.remaining is not None: + result["remaining"] = from_union([to_float, from_none], self.remaining) + if self.timestamp_utc is not None: + result["timestamp_utc"] = from_union([from_str, from_none], self.timestamp_utc) + if self.token_based_billing is not None: + result["token_based_billing"] = from_union([from_bool, from_none], self.token_based_billing) + if self.unlimited is not None: + result["unlimited"] = from_union([from_bool, from_none], self.unlimited) + return result + @dataclass class CurrentModel: - """The currently selected model for the session.""" + """The currently selected model and reasoning effort for the session.""" model_id: str | None = None """Currently active model identifier""" + reasoning_effort: str | None = None + """Reasoning effort level currently applied to the active model, when one is set. Reads + `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the + two values are reported as a snapshot. + """ + @staticmethod def from_dict(obj: Any) -> 'CurrentModel': assert isinstance(obj, dict) model_id = from_union([from_str, from_none], obj.get("modelId")) - return CurrentModel(model_id) + reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort")) + return CurrentModel(model_id, reasoning_effort) def to_dict(self) -> dict: result: dict = {} if self.model_id is not None: result["modelId"] = from_union([from_str, from_none], self.model_id) + if self.reasoning_effort is not None: + result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort) return result class DiscoveredMCPServerType(Enum): @@ -486,6 +735,161 @@ class DiscoveredMCPServerType(Enum): SSE = "sse" STDIO = "stdio" +@dataclass +class EnqueueCommandParams: + """Slash-prefixed command string to enqueue for FIFO processing.""" + + command: str + """Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO + with any in-flight items; if the session is idle, processing kicks off immediately. + """ + + @staticmethod + def from_dict(obj: Any) -> 'EnqueueCommandParams': + assert isinstance(obj, dict) + command = from_str(obj.get("command")) + return EnqueueCommandParams(command) + + def to_dict(self) -> dict: + result: dict = {} + result["command"] = from_str(self.command) + return result + +@dataclass +class EnqueueCommandResult: + """Indicates whether the command was accepted into the local execution queue.""" + + queued: bool + """True when the command was accepted into the local execution queue. False when the call + targets a session that does not support local command queueing (e.g. remote sessions). + """ + + @staticmethod + def from_dict(obj: Any) -> 'EnqueueCommandResult': + assert isinstance(obj, dict) + queued = from_bool(obj.get("queued")) + return EnqueueCommandResult(queued) + + def to_dict(self) -> dict: + result: dict = {} + result["queued"] = from_bool(self.queued) + return result + +class EnvAuthInfoType(Enum): + ENV = "env" + +# Experimental: this type is part of an experimental API and may change or be removed. +class EventsAgentScope(Enum): + """Agent-scope filter: 'primary' returns only main-agent events plus events whose type + starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns + events from all agents (matching wildcard-subscription behavior). Default is 'all' to + preserve wildcard semantics for catch-up callers. + """ + ALL = "all" + PRIMARY = "primary" + +# Experimental: this type is part of an experimental API and may change or be removed. +class EventLogTypes(Enum): + EMPTY = "*" + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class EventLogReleaseInterestResult: + """Indicates whether the operation succeeded.""" + + success: bool + """Whether the operation succeeded""" + + @staticmethod + def from_dict(obj: Any) -> 'EventLogReleaseInterestResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return EventLogReleaseInterestResult(success) + + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class EventLogTailResult: + """Snapshot of the current tail cursor without returning any events. Use this when a + consumer wants to subscribe to live events going forward without first paginating through + the entire persisted history (which would happen if `read` were called without a cursor + on a long-lived session). + """ + cursor: str + """Opaque cursor pointing at the current tail of the session's persisted-events history. + Pass back to `read` to receive only events that arrive AFTER this snapshot. When the + session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent + to omitting the cursor on a first read). + """ + + @staticmethod + def from_dict(obj: Any) -> 'EventLogTailResult': + assert isinstance(obj, dict) + cursor = from_str(obj.get("cursor")) + return EventLogTailResult(cursor) + + def to_dict(self) -> dict: + result: dict = {} + result["cursor"] = from_str(self.cursor) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +class EventsCursorStatus(Enum): + """Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor + referred to an event that no longer exists in history (e.g. truncated or compacted away) + and the read started from the beginning of the remaining history. + """ + EXPIRED = "expired" + OK = "ok" + +@dataclass +class ExecuteCommandParams: + """Slash command name and argument string to execute synchronously.""" + + args: str + """Argument string to pass to the command (empty string if none).""" + + command_name: str + """Name of the slash command to invoke (without the leading '/').""" + + @staticmethod + def from_dict(obj: Any) -> 'ExecuteCommandParams': + assert isinstance(obj, dict) + args = from_str(obj.get("args")) + command_name = from_str(obj.get("commandName")) + return ExecuteCommandParams(args, command_name) + + def to_dict(self) -> dict: + result: dict = {} + result["args"] = from_str(self.args) + result["commandName"] = from_str(self.command_name) + return result + +@dataclass +class ExecuteCommandResult: + """Error message produced while executing the command, if any.""" + + error: str | None = None + """Error message produced while executing the command, if any. Omitted when the handler + succeeded. + """ + + @staticmethod + def from_dict(obj: Any) -> 'ExecuteCommandResult': + assert isinstance(obj, dict) + error = from_union([from_str, from_none], obj.get("error")) + return ExecuteCommandResult(error) + + def to_dict(self) -> dict: + result: dict = {} + if self.error is not None: + result["error"] = from_union([from_str, from_none], self.error) + return result + # Experimental: this type is part of an experimental API and may change or be removed. class ExtensionSource(Enum): """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" @@ -618,6 +1022,9 @@ def to_dict(self) -> dict: result["started"] = from_bool(self.started) return result +class GhCLIAuthInfoType(Enum): + GH_CLI = "gh-cli" + @dataclass class HandlePendingToolCallResult: """Indicates whether the external tool call result was handled successfully.""" @@ -636,6 +1043,48 @@ def to_dict(self) -> dict: result["success"] = from_bool(self.success) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class HistoryAbortManualCompactionResult: + """Indicates whether an in-progress manual compaction was aborted.""" + + aborted: bool + """Whether an in-progress manual compaction was aborted. False when no manual compaction was + running, when its abort controller was already aborted, or when the session is remote. + """ + + @staticmethod + def from_dict(obj: Any) -> 'HistoryAbortManualCompactionResult': + assert isinstance(obj, dict) + aborted = from_bool(obj.get("aborted")) + return HistoryAbortManualCompactionResult(aborted) + + def to_dict(self) -> dict: + result: dict = {} + result["aborted"] = from_bool(self.aborted) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class HistoryCancelBackgroundCompactionResult: + """Indicates whether an in-progress background compaction was cancelled.""" + + cancelled: bool + """Whether an in-progress background compaction was cancelled. False when no compaction was + running, when the session is remote, or when the underlying processor was unavailable. + """ + + @staticmethod + def from_dict(obj: Any) -> 'HistoryCancelBackgroundCompactionResult': + assert isinstance(obj, dict) + cancelled = from_bool(obj.get("cancelled")) + return HistoryCancelBackgroundCompactionResult(cancelled) + + def to_dict(self) -> dict: + result: dict = {} + result["cancelled"] = from_bool(self.cancelled) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class HistoryCompactContextWindow: @@ -683,6 +1132,27 @@ def to_dict(self) -> dict: result["toolDefinitionsTokens"] = from_union([from_int, from_none], self.tool_definitions_tokens) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class HistorySummarizeForHandoffResult: + """Markdown summary of the conversation context (empty when not available).""" + + summary: str + """Markdown summary of the conversation context produced by an LLM. Empty string when there + are no messages or when the session does not support local summarization. + """ + + @staticmethod + def from_dict(obj: Any) -> 'HistorySummarizeForHandoffResult': + assert isinstance(obj, dict) + summary = from_str(obj.get("summary")) + return HistorySummarizeForHandoffResult(summary) + + def to_dict(self) -> dict: + result: dict = {} + result["summary"] = from_str(self.summary) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class HistoryTruncateRequest: @@ -721,10 +1191,28 @@ def to_dict(self) -> dict: result["eventsRemoved"] = from_int(self.events_removed) return result -class InstructionsSourcesLocation(Enum): - """Where this source lives — used for UI grouping""" +class HMACAuthInfoType(Enum): + HMAC = "hmac" - REPOSITORY = "repository" +class PurpleSource(Enum): + GITHUB = "github" + LOCAL = "local" + URL = "url" + +class FluffySource(Enum): + GITHUB = "github" + +class TentacledSource(Enum): + LOCAL = "local" + +class StickySource(Enum): + URL = "url" + +class InstructionsSourcesLocation(Enum): + """Where this source lives — used for UI grouping""" + + PLUGIN = "plugin" + REPOSITORY = "repository" USER = "user" WORKING_DIRECTORY = "working-directory" @@ -735,6 +1223,7 @@ class InstructionsSourcesType(Enum): HOME = "home" MODEL = "model" NESTED_AGENTS = "nested-agents" + PLUGIN = "plugin" REPO = "repo" VSCODE = "vscode" @@ -764,6 +1253,84 @@ def to_dict(self) -> dict: result["eventId"] = str(self.event_id) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class LspInitializeRequest: + """Parameters for (re)loading the merged LSP configuration set.""" + + force: bool | None = None + """Force re-initialization even when LSP configs were already loaded for the working + directory. + """ + git_root: str | None = None + """Git root used as the boundary when traversing for project-level LSP configs (supports + monorepos). + """ + working_directory: str | None = None + """Working directory used to load project-level LSP configs. Defaults to the session working + directory when omitted. + """ + + @staticmethod + def from_dict(obj: Any) -> 'LspInitializeRequest': + assert isinstance(obj, dict) + force = from_union([from_bool, from_none], obj.get("force")) + git_root = from_union([from_str, from_none], obj.get("gitRoot")) + working_directory = from_union([from_str, from_none], obj.get("workingDirectory")) + return LspInitializeRequest(force, git_root, working_directory) + + def to_dict(self) -> dict: + result: dict = {} + if self.force is not None: + result["force"] = from_union([from_bool, from_none], self.force) + if self.git_root is not None: + result["gitRoot"] = from_union([from_str, from_none], self.git_root) + if self.working_directory is not None: + result["workingDirectory"] = from_union([from_str, from_none], self.working_directory) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPCancelSamplingExecutionParams: + """The requestId previously passed to executeSampling that should be cancelled.""" + + request_id: str + """The requestId previously passed to executeSampling that should be cancelled""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPCancelSamplingExecutionParams': + assert isinstance(obj, dict) + request_id = from_str(obj.get("requestId")) + return MCPCancelSamplingExecutionParams(request_id) + + def to_dict(self) -> dict: + result: dict = {} + result["requestId"] = from_str(self.request_id) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPCancelSamplingExecutionResult: + """Indicates whether an in-flight sampling execution with the given requestId was found and + cancelled. + """ + cancelled: bool + """True if an in-flight execution with the given requestId was found and signalled to + cancel. False when no such execution is in flight (already completed, never started, or + cancelled by another caller). + """ + + @staticmethod + def from_dict(obj: Any) -> 'MCPCancelSamplingExecutionResult': + assert isinstance(obj, dict) + cancelled = from_bool(obj.get("cancelled")) + return MCPCancelSamplingExecutionResult(cancelled) + + def to_dict(self) -> dict: + result: dict = {} + result["cancelled"] = from_bool(self.cancelled) + return result + @dataclass class MCPServerConfigHTTPAuth: """Additional authentication configuration for this server.""" @@ -984,6 +1551,39 @@ def to_dict(self) -> dict: result["authorizationUrl"] = from_union([from_str, from_none], self.authorization_url) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPRemoveGitHubResult: + """Indicates whether the auto-managed `github` MCP server was removed (false when nothing to + remove). + """ + removed: bool + """True when the auto-managed `github` MCP server was removed; false when no removal + happened (e.g. user has explicitly configured a `github` server, or the server was not + registered). + """ + + @staticmethod + def from_dict(obj: Any) -> 'MCPRemoveGitHubResult': + assert isinstance(obj, dict) + removed = from_bool(obj.get("removed")) + return MCPRemoveGitHubResult(removed) + + def to_dict(self) -> dict: + result: dict = {} + result["removed"] = from_bool(self.removed) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +class MCPSamplingExecutionAction(Enum): + """Outcome of the sampling inference. 'success' produced a response; 'failure' encountered + an error (including agent-side rejection by content filter or criteria); 'cancelled' the + caller cancelled this execution via cancelSamplingExecution. + """ + CANCELLED = "cancelled" + FAILURE = "failure" + SUCCESS = "success" + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class MCPServer: @@ -1020,6 +1620,257 @@ def to_dict(self) -> dict: result["source"] = from_union([lambda x: to_enum(McpServerSource, x), from_none], self.source) return result +# Experimental: this type is part of an experimental API and may change or be removed. +class MCPSetEnvValueModeDetails(Enum): + """How environment-variable values supplied to MCP servers are resolved. "direct" passes + literal string values; "indirect" treats values as references (e.g. names of environment + variables on the host) that the runtime resolves before launch. Defaults to the runtime's + startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI + prompt mode and ACP) set this to "direct". + + Mode recorded on the session after the update + + How env values are passed to MCP servers (`direct` inlines literal values; `indirect` + resolves at launch). + """ + DIRECT = "direct" + INDIRECT = "indirect" + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionContextInfo: + """Token-usage breakdown for the session's current context window""" + + buffer_tokens: int + """Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%)""" + + compaction_threshold: int + """Token count at which background compaction starts (configurable percentage of + promptTokenLimit) + """ + conversation_tokens: int + """Tokens consumed by user/assistant/tool messages""" + + limit: int + """Total context limit for /context display. promptTokenLimit + min(32k or 64k, + outputTokenLimit) depending on model. + """ + model_name: str + """The model used for token counting""" + + prompt_token_limit: int + """Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified)""" + + system_tokens: int + """Tokens consumed by the system prompt""" + + tool_definitions_tokens: int + """Tokens consumed by tool definitions sent to the model (excludes deferred tools)""" + + total_tokens: int + """Sum of system, conversation and tool-definition tokens""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionContextInfo': + assert isinstance(obj, dict) + buffer_tokens = from_int(obj.get("bufferTokens")) + compaction_threshold = from_int(obj.get("compactionThreshold")) + conversation_tokens = from_int(obj.get("conversationTokens")) + limit = from_int(obj.get("limit")) + model_name = from_str(obj.get("modelName")) + prompt_token_limit = from_int(obj.get("promptTokenLimit")) + system_tokens = from_int(obj.get("systemTokens")) + tool_definitions_tokens = from_int(obj.get("toolDefinitionsTokens")) + total_tokens = from_int(obj.get("totalTokens")) + return SessionContextInfo(buffer_tokens, compaction_threshold, conversation_tokens, limit, model_name, prompt_token_limit, system_tokens, tool_definitions_tokens, total_tokens) + + def to_dict(self) -> dict: + result: dict = {} + result["bufferTokens"] = from_int(self.buffer_tokens) + result["compactionThreshold"] = from_int(self.compaction_threshold) + result["conversationTokens"] = from_int(self.conversation_tokens) + result["limit"] = from_int(self.limit) + result["modelName"] = from_str(self.model_name) + result["promptTokenLimit"] = from_int(self.prompt_token_limit) + result["systemTokens"] = from_int(self.system_tokens) + result["toolDefinitionsTokens"] = from_int(self.tool_definitions_tokens) + result["totalTokens"] = from_int(self.total_tokens) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataIsProcessingResult: + """Indicates whether the local session is currently processing a turn or background + continuation. + """ + processing: bool + """Whether the session is currently processing user/agent messages. False for non-local + sessions (which don't run a local agentic loop). Reflects an in-flight turn or background + continuation. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataIsProcessingResult': + assert isinstance(obj, dict) + processing = from_bool(obj.get("processing")) + return MetadataIsProcessingResult(processing) + + def to_dict(self) -> dict: + result: dict = {} + result["processing"] = from_bool(self.processing) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataRecomputeContextTokensResult: + """Re-tokenize the session's existing messages against `modelId` and return the token + totals. Useful for hosts that want an initial estimate of context usage on session + resume, before the next agent turn fires `session.context_info_changed` events. Returns + zeros for an empty session. + """ + messages_token_count: int + """Tokens contributed by user/assistant/tool messages (excludes system/developer prompts).""" + + system_token_count: int + """Tokens contributed by system/developer prompt snapshots.""" + + total_tokens: int + """Sum of tokens across chat-context and system-context messages currently held by the + session. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataRecomputeContextTokensResult': + assert isinstance(obj, dict) + messages_token_count = from_int(obj.get("messagesTokenCount")) + system_token_count = from_int(obj.get("systemTokenCount")) + total_tokens = from_int(obj.get("totalTokens")) + return MetadataRecomputeContextTokensResult(messages_token_count, system_token_count, total_tokens) + + def to_dict(self) -> dict: + result: dict = {} + result["messagesTokenCount"] = from_int(self.messages_token_count) + result["systemTokenCount"] = from_int(self.system_token_count) + result["totalTokens"] = from_int(self.total_tokens) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +class SessionContextHostType(Enum): + """Hosting platform type of the repository + + Repository host type + + Repository host type, if known + """ + ADO = "ado" + GITHUB = "github" + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataRecordContextChangeResult: + """Notify the session that its working directory context has changed. Emits a + `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline + UI) can react. Use this when the host has detected a cwd/branch/repo change outside the + session's normal lifecycle (e.g., after a shell command in interactive mode). + """ + @staticmethod + def from_dict(obj: Any) -> 'MetadataRecordContextChangeResult': + assert isinstance(obj, dict) + return MetadataRecordContextChangeResult() + + 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 MetadataSetWorkingDirectoryRequest: + """Absolute path to set as the session's new working directory.""" + + working_directory: str + """Absolute path to set as the session's working directory. The runtime updates the + session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) + anchor to it. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataSetWorkingDirectoryRequest': + assert isinstance(obj, dict) + working_directory = from_str(obj.get("workingDirectory")) + return MetadataSetWorkingDirectoryRequest(working_directory) + + def to_dict(self) -> dict: + result: dict = {} + result["workingDirectory"] = from_str(self.working_directory) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataSetWorkingDirectoryResult: + """Update the session's working directory. Used by the host when the user explicitly changes + cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any + related side-effects (file index, etc.); this method only updates the session's own + recorded path. + """ + working_directory: str + """Working directory after the update""" + + @staticmethod + def from_dict(obj: Any) -> 'MetadataSetWorkingDirectoryResult': + assert isinstance(obj, dict) + working_directory = from_str(obj.get("workingDirectory")) + return MetadataSetWorkingDirectoryResult(working_directory) + + def to_dict(self) -> dict: + result: dict = {} + result["workingDirectory"] = from_str(self.working_directory) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +class MetadataSnapshotCurrentMode(Enum): + """The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot')""" + + AUTOPILOT = "autopilot" + INTERACTIVE = "interactive" + PLAN = "plan" + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataSnapshotRemoteMetadataRepository: + """The repository the remote session targets.""" + + branch: str + """The branch the remote session is operating on.""" + + name: str + """The GitHub repository name (without owner).""" + + owner: str + """The GitHub owner (user or organization) of the target repository.""" + + @staticmethod + def from_dict(obj: Any) -> 'MetadataSnapshotRemoteMetadataRepository': + assert isinstance(obj, dict) + branch = from_str(obj.get("branch")) + name = from_str(obj.get("name")) + owner = from_str(obj.get("owner")) + return MetadataSnapshotRemoteMetadataRepository(branch, name, owner) + + def to_dict(self) -> dict: + result: dict = {} + result["branch"] = from_str(self.branch) + result["name"] = from_str(self.name) + result["owner"] = from_str(self.owner) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +class MetadataSnapshotRemoteMetadataTaskType(Enum): + """Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` + invocation. + """ + CCA = "cca" + CLI = "cli" + @dataclass class ModeSetRequest: """Agent interaction mode to apply to the session.""" @@ -1203,6 +2054,46 @@ def to_dict(self) -> dict: result["vision"] = from_union([from_bool, from_none], self.vision) return result +@dataclass +class ModelSetReasoningEffortRequest: + """Reasoning effort level to apply to the currently selected model.""" + + reasoning_effort: str + """Reasoning effort level to apply to the currently selected model. The host is responsible + for validating the value against the model's supported levels before calling. + """ + + @staticmethod + def from_dict(obj: Any) -> 'ModelSetReasoningEffortRequest': + assert isinstance(obj, dict) + reasoning_effort = from_str(obj.get("reasoningEffort")) + return ModelSetReasoningEffortRequest(reasoning_effort) + + def to_dict(self) -> dict: + result: dict = {} + result["reasoningEffort"] = from_str(self.reasoning_effort) + return result + +@dataclass +class ModelSetReasoningEffortResult: + """Update the session's reasoning effort without changing the selected model. Use `switchTo` + instead when you also need to change the model. The runtime stores the effort on the + session and applies it to subsequent turns. + """ + reasoning_effort: str + """Reasoning effort level recorded on the session after the update""" + + @staticmethod + def from_dict(obj: Any) -> 'ModelSetReasoningEffortResult': + assert isinstance(obj, dict) + reasoning_effort = from_str(obj.get("reasoningEffort")) + return ModelSetReasoningEffortResult(reasoning_effort) + + def to_dict(self) -> dict: + result: dict = {} + result["reasoningEffort"] = from_str(self.reasoning_effort) + return result + @dataclass class ModelSwitchToResult: """The model identifier active on the session after the switch.""" @@ -1259,6 +2150,47 @@ def to_dict(self) -> dict: result["name"] = from_union([from_none, from_str], self.name) return result +@dataclass +class NameSetAutoRequest: + """Auto-generated session summary to apply as the session's name when no user-set name + exists. + """ + summary: str + """Auto-generated session summary. Empty/whitespace-only values are ignored; values are + trimmed before persisting. + """ + + @staticmethod + def from_dict(obj: Any) -> 'NameSetAutoRequest': + assert isinstance(obj, dict) + summary = from_str(obj.get("summary")) + return NameSetAutoRequest(summary) + + def to_dict(self) -> dict: + result: dict = {} + result["summary"] = from_str(self.summary) + return result + +@dataclass +class NameSetAutoResult: + """Indicates whether the auto-generated summary was applied as the session's name.""" + + applied: bool + """Whether the auto-generated summary was persisted. False if the session already has a + user-set name, the summary normalized to empty, or the session does not have a workspace. + """ + + @staticmethod + def from_dict(obj: Any) -> 'NameSetAutoResult': + assert isinstance(obj, dict) + applied = from_bool(obj.get("applied")) + return NameSetAutoResult(applied) + + def to_dict(self) -> dict: + result: dict = {} + result["applied"] = from_bool(self.applied) + return result + @dataclass class NameSetRequest: """New friendly name to apply to the session.""" @@ -1277,22 +2209,55 @@ def to_dict(self) -> dict: result["name"] = from_str(self.name) return result -class ApprovalKind(Enum): - COMMANDS = "commands" - CUSTOM_TOOL = "custom-tool" - EXTENSION_MANAGEMENT = "extension-management" - EXTENSION_PERMISSION_ACCESS = "extension-permission-access" - MCP = "mcp" - MCP_SAMPLING = "mcp-sampling" - MEMORY = "memory" - READ = "read" - WRITE = "write" +@dataclass +class PendingPermissionRequest: + """Schema for the `PendingPermissionRequest` type.""" -class PermissionDecisionKind(Enum): - APPROVE_FOR_LOCATION = "approve-for-location" + request: PermissionPromptRequest + """The user-facing permission prompt details (commands, write, read, mcp, url, memory, + custom-tool, path, hook) + """ + request_id: str + """Unique identifier for the pending permission request""" + + @staticmethod + def from_dict(obj: Any) -> 'PendingPermissionRequest': + assert isinstance(obj, dict) + request = PermissionPromptRequest.from_dict(obj.get("request")) + request_id = from_str(obj.get("requestId")) + return PendingPermissionRequest(request, request_id) + + def to_dict(self) -> dict: + result: dict = {} + result["request"] = to_class(PermissionPromptRequest, self.request) + result["requestId"] = from_str(self.request_id) + return result + +class ApprovalKind(Enum): + COMMANDS = "commands" + CUSTOM_TOOL = "custom-tool" + EXTENSION_MANAGEMENT = "extension-management" + EXTENSION_PERMISSION_ACCESS = "extension-permission-access" + MCP = "mcp" + MCP_SAMPLING = "mcp-sampling" + MEMORY = "memory" + READ = "read" + WRITE = "write" + +class PermissionDecisionKind(Enum): + APPROVED = "approved" + APPROVED_FOR_LOCATION = "approved-for-location" + APPROVED_FOR_SESSION = "approved-for-session" + APPROVE_FOR_LOCATION = "approve-for-location" APPROVE_FOR_SESSION = "approve-for-session" APPROVE_ONCE = "approve-once" APPROVE_PERMANENTLY = "approve-permanently" + CANCELLED = "cancelled" + DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy" + DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook" + DENIED_BY_RULES = "denied-by-rules" + DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user" + DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user" REJECT = "reject" USER_NOT_AVAILABLE = "user-not-available" @@ -1335,6 +2300,33 @@ class PermissionDecisionApproveOnceKind(Enum): class PermissionDecisionApprovePermanentlyKind(Enum): APPROVE_PERMANENTLY = "approve-permanently" +class PermissionDecisionApprovedKind(Enum): + APPROVED = "approved" + +class PermissionDecisionApprovedForLocationKind(Enum): + APPROVED_FOR_LOCATION = "approved-for-location" + +class PermissionDecisionApprovedForSessionKind(Enum): + APPROVED_FOR_SESSION = "approved-for-session" + +class PermissionDecisionCancelledKind(Enum): + CANCELLED = "cancelled" + +class PermissionDecisionDeniedByContentExclusionPolicyKind(Enum): + DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy" + +class PermissionDecisionDeniedByPermissionRequestHookKind(Enum): + DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook" + +class PermissionDecisionDeniedByRulesKind(Enum): + DENIED_BY_RULES = "denied-by-rules" + +class PermissionDecisionDeniedInteractivelyByUserKind(Enum): + DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user" + +class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind(Enum): + DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user" + class PermissionDecisionRejectKind(Enum): REJECT = "reject" @@ -1342,4550 +2334,8632 @@ class PermissionDecisionUserNotAvailableKind(Enum): USER_NOT_AVAILABLE = "user-not-available" @dataclass -class PermissionRequestResult: - """Indicates whether the permission decision was applied; false when the request was already - resolved. +class PermissionPathsAddParams: + """Directory path to add to the session's allowed directories.""" + + path: str + """Directory to add to the allow-list. The runtime resolves and validates the path before + adding. """ - success: bool - """Whether the permission request was handled successfully""" @staticmethod - def from_dict(obj: Any) -> 'PermissionRequestResult': + def from_dict(obj: Any) -> 'PermissionPathsAddParams': assert isinstance(obj, dict) - success = from_bool(obj.get("success")) - return PermissionRequestResult(success) + path = from_str(obj.get("path")) + return PermissionPathsAddParams(path) def to_dict(self) -> dict: result: dict = {} - result["success"] = from_bool(self.success) + result["path"] = from_str(self.path) return result @dataclass -class PermissionsResetSessionApprovalsRequest: - """No parameters; clears all session-scoped tool permission approvals.""" +class PermissionPathsAllowedCheckParams: + """Path to evaluate against the session's allowed directories.""" + + path: str + """Path to check against the session's allowed directories""" + @staticmethod - def from_dict(obj: Any) -> 'PermissionsResetSessionApprovalsRequest': + def from_dict(obj: Any) -> 'PermissionPathsAllowedCheckParams': assert isinstance(obj, dict) - return PermissionsResetSessionApprovalsRequest() + path = from_str(obj.get("path")) + return PermissionPathsAllowedCheckParams(path) def to_dict(self) -> dict: result: dict = {} + result["path"] = from_str(self.path) return result @dataclass -class PermissionsResetSessionApprovalsResult: - """Indicates whether the operation succeeded.""" +class PermissionPathsAllowedCheckResult: + """Indicates whether the supplied path is within the session's allowed directories.""" - success: bool - """Whether the operation succeeded""" + allowed: bool + """Whether the path is within the session's allowed directories""" @staticmethod - def from_dict(obj: Any) -> 'PermissionsResetSessionApprovalsResult': + def from_dict(obj: Any) -> 'PermissionPathsAllowedCheckResult': assert isinstance(obj, dict) - success = from_bool(obj.get("success")) - return PermissionsResetSessionApprovalsResult(success) + allowed = from_bool(obj.get("allowed")) + return PermissionPathsAllowedCheckResult(allowed) def to_dict(self) -> dict: result: dict = {} - result["success"] = from_bool(self.success) + result["allowed"] = from_bool(self.allowed) return result @dataclass -class PermissionsSetApproveAllRequest: - """Whether to auto-approve all tool permission requests for the rest of the session.""" +class PermissionPathsList: + """Snapshot of the session's allow-listed directories and primary working directory.""" - enabled: bool - """Whether to auto-approve all tool permission requests""" + directories: list[str] + """All directories currently allowed for tool access on this session.""" + + primary: str + """The primary working directory for this session.""" @staticmethod - def from_dict(obj: Any) -> 'PermissionsSetApproveAllRequest': + def from_dict(obj: Any) -> 'PermissionPathsList': assert isinstance(obj, dict) - enabled = from_bool(obj.get("enabled")) - return PermissionsSetApproveAllRequest(enabled) + directories = from_list(from_str, obj.get("directories")) + primary = from_str(obj.get("primary")) + return PermissionPathsList(directories, primary) def to_dict(self) -> dict: result: dict = {} - result["enabled"] = from_bool(self.enabled) + result["directories"] = from_list(from_str, self.directories) + result["primary"] = from_str(self.primary) return result @dataclass -class PermissionsSetApproveAllResult: - """Indicates whether the operation succeeded.""" +class PermissionPathsUpdatePrimaryParams: + """Directory path to set as the session's new primary working directory.""" - success: bool - """Whether the operation succeeded""" + path: str + """Directory to set as the new primary working directory for the session's permission policy.""" @staticmethod - def from_dict(obj: Any) -> 'PermissionsSetApproveAllResult': + def from_dict(obj: Any) -> 'PermissionPathsUpdatePrimaryParams': assert isinstance(obj, dict) - success = from_bool(obj.get("success")) - return PermissionsSetApproveAllResult(success) + path = from_str(obj.get("path")) + return PermissionPathsUpdatePrimaryParams(path) def to_dict(self) -> dict: result: dict = {} - result["success"] = from_bool(self.success) + result["path"] = from_str(self.path) return result @dataclass -class PingRequest: - """Optional message to echo back to the caller.""" +class PermissionPathsWorkspaceCheckParams: + """Path to evaluate against the session's workspace (primary) directory.""" - message: str | None = None - """Optional message to echo back""" + path: str + """Path to check against the session workspace directory""" @staticmethod - def from_dict(obj: Any) -> 'PingRequest': + def from_dict(obj: Any) -> 'PermissionPathsWorkspaceCheckParams': assert isinstance(obj, dict) - message = from_union([from_str, from_none], obj.get("message")) - return PingRequest(message) + path = from_str(obj.get("path")) + return PermissionPathsWorkspaceCheckParams(path) def to_dict(self) -> dict: result: dict = {} - if self.message is not None: - result["message"] = from_union([from_str, from_none], self.message) + result["path"] = from_str(self.path) return result @dataclass -class PingResult: - """Server liveness response, including the echoed message, current timestamp, and protocol - version. - """ - message: str - """Echoed message (or default greeting)""" +class PermissionPathsWorkspaceCheckResult: + """Indicates whether the supplied path is within the session's workspace directory.""" - protocol_version: int - """Server protocol version number""" - - timestamp: int - """Server timestamp in milliseconds""" + allowed: bool + """Whether the path is within the session workspace directory""" @staticmethod - def from_dict(obj: Any) -> 'PingResult': + def from_dict(obj: Any) -> 'PermissionPathsWorkspaceCheckResult': assert isinstance(obj, dict) - message = from_str(obj.get("message")) - protocol_version = from_int(obj.get("protocolVersion")) - timestamp = from_int(obj.get("timestamp")) - return PingResult(message, protocol_version, timestamp) + allowed = from_bool(obj.get("allowed")) + return PermissionPathsWorkspaceCheckResult(allowed) def to_dict(self) -> dict: result: dict = {} - result["message"] = from_str(self.message) - result["protocolVersion"] = from_int(self.protocol_version) - result["timestamp"] = from_int(self.timestamp) + result["allowed"] = from_bool(self.allowed) return result @dataclass -class PlanReadResult: - """Existence, contents, and resolved path of the session plan file.""" +class PermissionPromptShownNotification: + """Notification payload describing the permission prompt that the client just rendered.""" - exists: bool - """Whether the plan file exists in the workspace""" + message: str + """Human-readable description of the prompt the user is being asked to approve. Used by the + runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, + desktop notification). + """ - content: str | None = None - """The content of the plan file, or null if it does not exist""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionPromptShownNotification': + assert isinstance(obj, dict) + message = from_str(obj.get("message")) + return PermissionPromptShownNotification(message) - path: str | None = None - """Absolute file path of the plan file, or null if workspace is not enabled""" + def to_dict(self) -> dict: + result: dict = {} + result["message"] = from_str(self.message) + return result + +@dataclass +class PermissionRequestResult: + """Indicates whether the permission decision was applied; false when the request was already + resolved. + """ + success: bool + """Whether the permission request was handled successfully""" @staticmethod - def from_dict(obj: Any) -> 'PlanReadResult': + def from_dict(obj: Any) -> 'PermissionRequestResult': 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 PlanReadResult(exists, content, path) + success = from_bool(obj.get("success")) + return PermissionRequestResult(success) def to_dict(self) -> dict: result: dict = {} - result["exists"] = from_bool(self.exists) - result["content"] = from_union([from_none, from_str], self.content) - result["path"] = from_union([from_none, from_str], self.path) + result["success"] = from_bool(self.success) return result @dataclass -class PlanUpdateRequest: - """Replacement contents to write to the session plan file.""" +class PermissionRulesSet: + """If specified, replaces the session's approved/denied permission rules. Omit to leave the + current rules unchanged. + """ + approved: list[PermissionRule] + """Rules that auto-approve matching requests""" - content: str - """The new content for the plan file""" + denied: list[PermissionRule] + """Rules that auto-deny matching requests""" @staticmethod - def from_dict(obj: Any) -> 'PlanUpdateRequest': + def from_dict(obj: Any) -> 'PermissionRulesSet': assert isinstance(obj, dict) - content = from_str(obj.get("content")) - return PlanUpdateRequest(content) + approved = from_list(PermissionRule.from_dict, obj.get("approved")) + denied = from_list(PermissionRule.from_dict, obj.get("denied")) + return PermissionRulesSet(approved, denied) def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) + result["approved"] = from_list(lambda x: to_class(PermissionRule, x), self.approved) + result["denied"] = from_list(lambda x: to_class(PermissionRule, x), self.denied) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class Plugin: - """Schema for the `Plugin` type.""" +class PermissionUrlsConfig: + """If specified, replaces the session's URL-permission policy. The runtime constructs a + fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy + unchanged. + """ + initial_allowed: list[str] | None = None + """Initial list of allowed URL/domain patterns. Patterns may include path components. + Ignored when `unrestricted` is true. + """ + unrestricted: bool | None = None + """If true, the runtime allows access to all URLs without prompting. Initial allow-list is + ignored when this is true. + """ - enabled: bool - """Whether the plugin is currently enabled""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionUrlsConfig': + assert isinstance(obj, dict) + initial_allowed = from_union([lambda x: from_list(from_str, x), from_none], obj.get("initialAllowed")) + unrestricted = from_union([from_bool, from_none], obj.get("unrestricted")) + return PermissionUrlsConfig(initial_allowed, unrestricted) - marketplace: str - """Marketplace the plugin came from""" + def to_dict(self) -> dict: + result: dict = {} + if self.initial_allowed is not None: + result["initialAllowed"] = from_union([lambda x: from_list(from_str, x), from_none], self.initial_allowed) + if self.unrestricted is not None: + result["unrestricted"] = from_union([from_bool, from_none], self.unrestricted) + return result - name: str - """Plugin name""" +@dataclass +class PermissionUrlsSetUnrestrictedModeParams: + """Whether the URL-permission policy should run in unrestricted mode.""" - version: str | None = None - """Installed version""" + enabled: bool + """Whether to allow access to all URLs without prompting. Toggles the runtime's + URL-permission policy in place. + """ @staticmethod - def from_dict(obj: Any) -> 'Plugin': + def from_dict(obj: Any) -> 'PermissionUrlsSetUnrestrictedModeParams': assert isinstance(obj, dict) enabled = from_bool(obj.get("enabled")) - marketplace = from_str(obj.get("marketplace")) - name = from_str(obj.get("name")) - version = from_union([from_str, from_none], obj.get("version")) - return Plugin(enabled, marketplace, name, version) + return PermissionUrlsSetUnrestrictedModeParams(enabled) def to_dict(self) -> dict: result: dict = {} result["enabled"] = from_bool(self.enabled) - result["marketplace"] = from_str(self.marketplace) - result["name"] = from_str(self.name) - if self.version is not None: - result["version"] = from_union([from_str, from_none], self.version) return result @dataclass -class QueuedCommandHandled: - """Schema for the `QueuedCommandHandled` type.""" +class PermissionsConfigureAdditionalContentExclusionPolicyRuleSource: + """Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type.""" - handled: bool - """The command was handled""" - - stop_processing_queue: bool | None = None - """If true, stop processing remaining queued items""" + name: str + type: str @staticmethod - def from_dict(obj: Any) -> 'QueuedCommandHandled': + def from_dict(obj: Any) -> 'PermissionsConfigureAdditionalContentExclusionPolicyRuleSource': assert isinstance(obj, dict) - handled = from_bool(obj.get("handled")) - stop_processing_queue = from_union([from_bool, from_none], obj.get("stopProcessingQueue")) - return QueuedCommandHandled(handled, stop_processing_queue) + name = from_str(obj.get("name")) + type = from_str(obj.get("type")) + return PermissionsConfigureAdditionalContentExclusionPolicyRuleSource(name, type) def to_dict(self) -> dict: result: dict = {} - result["handled"] = from_bool(self.handled) - if self.stop_processing_queue is not None: - result["stopProcessingQueue"] = from_union([from_bool, from_none], self.stop_processing_queue) + result["name"] = from_str(self.name) + result["type"] = from_str(self.type) return result +class PermissionsConfigureAdditionalContentExclusionPolicyScope(Enum): + """Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` + enumeration. + """ + ALL = "all" + REPO = "repo" + @dataclass -class QueuedCommandNotHandled: - """Schema for the `QueuedCommandNotHandled` type.""" +class PermissionsConfigureResult: + """Indicates whether the operation succeeded.""" - handled: bool - """The command was not handled""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'QueuedCommandNotHandled': + def from_dict(obj: Any) -> 'PermissionsConfigureResult': assert isinstance(obj, dict) - handled = from_bool(obj.get("handled")) - return QueuedCommandNotHandled(handled) + success = from_bool(obj.get("success")) + return PermissionsConfigureResult(success) def to_dict(self) -> dict: result: dict = {} - result["handled"] = from_bool(self.handled) + result["success"] = from_bool(self.success) return result -# Experimental: this type is part of an experimental API and may change or be removed. -class RemoteSessionMode(Enum): - """Per-session remote mode. "off" disables remote, "export" exports session events to GitHub - without enabling remote steering, "on" enables both export and remote steering. +class PermissionsModifyRulesScope(Enum): + """Whether the change applies to ephemeral session-scoped rules (cleared at session end) or + to location-scoped rules persisted via the location-permissions config file. """ - EXPORT = "export" - OFF = "off" - ON = "on" + LOCATION = "location" + SESSION = "session" -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class RemoteEnableResult: - """GitHub URL for the session and a flag indicating whether remote steering is enabled.""" - - remote_steerable: bool - """Whether remote steering is enabled""" +class PermissionsModifyRulesResult: + """Indicates whether the operation succeeded.""" - url: str | None = None - """GitHub frontend URL for this session""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'RemoteEnableResult': + def from_dict(obj: Any) -> 'PermissionsModifyRulesResult': assert isinstance(obj, dict) - remote_steerable = from_bool(obj.get("remoteSteerable")) - url = from_union([from_str, from_none], obj.get("url")) - return RemoteEnableResult(remote_steerable, url) + success = from_bool(obj.get("success")) + return PermissionsModifyRulesResult(success) def to_dict(self) -> dict: result: dict = {} - result["remoteSteerable"] = from_bool(self.remote_steerable) - if self.url is not None: - result["url"] = from_union([from_str, from_none], self.url) + result["success"] = from_bool(self.success) return result @dataclass -class ServerSkill: - """Schema for the `ServerSkill` type.""" +class PermissionsNotifyPromptShownResult: + """Indicates whether the operation succeeded.""" - description: str - """Description of what the skill does""" + success: bool + """Whether the operation succeeded""" - enabled: bool - """Whether the skill is currently enabled (based on global config)""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionsNotifyPromptShownResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return PermissionsNotifyPromptShownResult(success) - name: str - """Unique identifier for the skill""" + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result - source: SkillSource - """Source location type (e.g., project, personal-copilot, plugin, builtin)""" +@dataclass +class PermissionsPathsAddResult: + """Indicates whether the operation succeeded.""" - user_invocable: bool - """Whether the skill can be invoked by the user as a slash command""" + success: bool + """Whether the operation succeeded""" - path: str | None = None - """Absolute path to the skill file""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionsPathsAddResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return PermissionsPathsAddResult(success) - project_path: str | None = None - """The project path this skill belongs to (only for project/inherited skills)""" + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result +@dataclass +class PermissionsPathsListRequest: + """No parameters; returns the session's allow-listed directories.""" @staticmethod - def from_dict(obj: Any) -> 'ServerSkill': + def from_dict(obj: Any) -> 'PermissionsPathsListRequest': assert isinstance(obj, dict) - description = from_str(obj.get("description")) - enabled = from_bool(obj.get("enabled")) - name = from_str(obj.get("name")) - source = SkillSource(obj.get("source")) - user_invocable = from_bool(obj.get("userInvocable")) - path = from_union([from_str, from_none], obj.get("path")) - project_path = from_union([from_str, from_none], obj.get("projectPath")) - return ServerSkill(description, enabled, name, source, user_invocable, path, project_path) + return PermissionsPathsListRequest() def to_dict(self) -> dict: result: dict = {} - result["description"] = from_str(self.description) - result["enabled"] = from_bool(self.enabled) - result["name"] = from_str(self.name) - result["source"] = to_enum(SkillSource, self.source) - result["userInvocable"] = from_bool(self.user_invocable) - if self.path is not None: - result["path"] = from_union([from_str, from_none], self.path) - if self.project_path is not None: - result["projectPath"] = from_union([from_str, from_none], self.project_path) return result @dataclass -class SessionFSAppendFileRequest: - """File path, content to append, and optional mode for the client-provided session - filesystem. - """ - content: str - """Content to append""" +class PermissionsPathsUpdatePrimaryResult: + """Indicates whether the operation succeeded.""" - path: str - """Path using SessionFs conventions""" + success: bool + """Whether the operation succeeded""" - session_id: str - """Target session identifier""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionsPathsUpdatePrimaryResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return PermissionsPathsUpdatePrimaryResult(success) - mode: int | None = None - """Optional POSIX-style mode for newly created files""" + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result +@dataclass +class PermissionsPendingRequestsRequest: + """No parameters; returns currently-pending permission requests for the session.""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSAppendFileRequest': + def from_dict(obj: Any) -> 'PermissionsPendingRequestsRequest': 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_int, from_none], obj.get("mode")) - return SessionFSAppendFileRequest(content, path, session_id, mode) + return PermissionsPendingRequestsRequest() def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) - if self.mode is not None: - result["mode"] = from_union([from_int, from_none], self.mode) return result -class SessionFSErrorCode(Enum): - """Error classification""" +@dataclass +class PermissionsResetSessionApprovalsRequest: + """No parameters; clears all session-scoped tool permission approvals.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionsResetSessionApprovalsRequest': + assert isinstance(obj, dict) + return PermissionsResetSessionApprovalsRequest() - ENOENT = "ENOENT" - UNKNOWN = "UNKNOWN" + def to_dict(self) -> dict: + result: dict = {} + return result @dataclass -class SessionFSExistsRequest: - """Path to test for existence in the client-provided session filesystem.""" - - path: str - """Path using SessionFs conventions""" +class PermissionsResetSessionApprovalsResult: + """Indicates whether the operation succeeded.""" - session_id: str - """Target session identifier""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSExistsRequest': + def from_dict(obj: Any) -> 'PermissionsResetSessionApprovalsResult': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - return SessionFSExistsRequest(path, session_id) + success = from_bool(obj.get("success")) + return PermissionsResetSessionApprovalsResult(success) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) + result["success"] = from_bool(self.success) return result @dataclass -class SessionFSExistsResult: - """Indicates whether the requested path exists in the client-provided session filesystem.""" +class PermissionsSetApproveAllResult: + """Indicates whether the operation succeeded.""" - exists: bool - """Whether the path exists""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSExistsResult': + def from_dict(obj: Any) -> 'PermissionsSetApproveAllResult': assert isinstance(obj, dict) - exists = from_bool(obj.get("exists")) - return SessionFSExistsResult(exists) + success = from_bool(obj.get("success")) + return PermissionsSetApproveAllResult(success) def to_dict(self) -> dict: result: dict = {} - result["exists"] = from_bool(self.exists) + result["success"] = from_bool(self.success) return result @dataclass -class SessionFSMkdirRequest: - """Directory path to create in the client-provided session filesystem, with options for - recursive creation and POSIX mode. - """ - path: str - """Path using SessionFs conventions""" - - session_id: str - """Target session identifier""" - - mode: int | None = None - """Optional POSIX-style mode for newly created directories""" +class PermissionsSetRequiredRequest: + """Toggles whether permission prompts should be bridged into session events for this client.""" - recursive: bool | None = None - """Create parent directories as needed""" + required: bool + """Whether the client wants `permission.requested` events bridged from the session-owned + permission service. CLI clients that render prompt UI set this to `true` for as long as + their listener is mounted; headless callers leave it unset (the default is `false`). + """ @staticmethod - def from_dict(obj: Any) -> 'SessionFSMkdirRequest': + def from_dict(obj: Any) -> 'PermissionsSetRequiredRequest': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - mode = from_union([from_int, from_none], obj.get("mode")) - recursive = from_union([from_bool, from_none], obj.get("recursive")) - return SessionFSMkdirRequest(path, session_id, mode, recursive) + required = from_bool(obj.get("required")) + return PermissionsSetRequiredRequest(required) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) - if self.mode is not None: - result["mode"] = from_union([from_int, from_none], self.mode) - if self.recursive is not None: - result["recursive"] = from_union([from_bool, from_none], self.recursive) + result["required"] = from_bool(self.required) return result @dataclass -class SessionFSReadFileRequest: - """Path of the file to read from the client-provided session filesystem.""" - - path: str - """Path using SessionFs conventions""" +class PermissionsSetRequiredResult: + """Indicates whether the operation succeeded.""" - session_id: str - """Target session identifier""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReadFileRequest': + def from_dict(obj: Any) -> 'PermissionsSetRequiredResult': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - return SessionFSReadFileRequest(path, session_id) + success = from_bool(obj.get("success")) + return PermissionsSetRequiredResult(success) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) + result["success"] = from_bool(self.success) return result @dataclass -class SessionFSReaddirRequest: - """Directory path whose entries should be listed from the client-provided session filesystem.""" - - path: str - """Path using SessionFs conventions""" +class PermissionsUrlsSetUnrestrictedModeResult: + """Indicates whether the operation succeeded.""" - session_id: str - """Target session identifier""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReaddirRequest': + def from_dict(obj: Any) -> 'PermissionsUrlsSetUnrestrictedModeResult': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - return SessionFSReaddirRequest(path, session_id) + success = from_bool(obj.get("success")) + return PermissionsUrlsSetUnrestrictedModeResult(success) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) + result["success"] = from_bool(self.success) return result -class SessionFSReaddirWithTypesEntryType(Enum): - """Entry type""" - - DIRECTORY = "directory" - FILE = "file" - @dataclass -class SessionFSReaddirWithTypesRequest: - """Directory path whose entries (with type information) should be listed from the - client-provided session filesystem. - """ - path: str - """Path using SessionFs conventions""" +class PingRequest: + """Optional message to echo back to the caller.""" - session_id: str - """Target session identifier""" + message: str | None = None + """Optional message to echo back""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesRequest': + def from_dict(obj: Any) -> 'PingRequest': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - return SessionFSReaddirWithTypesRequest(path, session_id) + message = from_union([from_str, from_none], obj.get("message")) + return PingRequest(message) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) + if self.message is not None: + result["message"] = from_union([from_str, from_none], self.message) return result @dataclass -class SessionFSRenameRequest: - """Source and destination paths for renaming or moving an entry in the client-provided - session filesystem. +class PingResult: + """Server liveness response, including the echoed message, current server timestamp, and + protocol version. """ - dest: str - """Destination path using SessionFs conventions""" + message: str + """Echoed message (or default greeting)""" - session_id: str - """Target session identifier""" + protocol_version: int + """Server protocol version number""" - src: str - """Source path using SessionFs conventions""" + timestamp: datetime + """ISO 8601 timestamp when the server handled the ping""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSRenameRequest': + def from_dict(obj: Any) -> 'PingResult': assert isinstance(obj, dict) - dest = from_str(obj.get("dest")) - session_id = from_str(obj.get("sessionId")) - src = from_str(obj.get("src")) - return SessionFSRenameRequest(dest, session_id, src) + message = from_str(obj.get("message")) + protocol_version = from_int(obj.get("protocolVersion")) + timestamp = from_datetime(obj.get("timestamp")) + return PingResult(message, protocol_version, timestamp) def to_dict(self) -> dict: result: dict = {} - result["dest"] = from_str(self.dest) - result["sessionId"] = from_str(self.session_id) - result["src"] = from_str(self.src) + result["message"] = from_str(self.message) + result["protocolVersion"] = from_int(self.protocol_version) + result["timestamp"] = self.timestamp.isoformat() return result @dataclass -class SessionFSRmRequest: - """Path to remove from the client-provided session filesystem, with options for recursive - removal and force. - """ - path: str - """Path using SessionFs conventions""" +class PlanReadResult: + """Existence, contents, and resolved path of the session plan file.""" - session_id: str - """Target session identifier""" + exists: bool + """Whether the plan file exists in the workspace""" - force: bool | None = None - """Ignore errors if the path does not exist""" + content: str | None = None + """The content of the plan file, or null if it does not exist""" - recursive: bool | None = None - """Remove directories and their contents recursively""" + path: str | None = None + """Absolute file path of the plan file, or null if workspace is not enabled""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSRmRequest': + def from_dict(obj: Any) -> 'PlanReadResult': 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 SessionFSRmRequest(path, session_id, force, recursive) + 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 PlanReadResult(exists, content, path) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) - if self.force is not None: - result["force"] = from_union([from_bool, from_none], self.force) - if self.recursive is not None: - result["recursive"] = from_union([from_bool, from_none], self.recursive) + result["exists"] = from_bool(self.exists) + result["content"] = from_union([from_none, from_str], self.content) + result["path"] = from_union([from_none, from_str], self.path) return result @dataclass -class SessionFSSetProviderCapabilities: - """Optional capabilities declared by the provider""" +class PlanUpdateRequest: + """Replacement contents to write to the session plan file.""" - sqlite: bool | None = None - """Whether the provider supports SQLite query/exists operations""" + content: str + """The new content for the plan file""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSSetProviderCapabilities': + def from_dict(obj: Any) -> 'PlanUpdateRequest': assert isinstance(obj, dict) - sqlite = from_union([from_bool, from_none], obj.get("sqlite")) - return SessionFSSetProviderCapabilities(sqlite) + content = from_str(obj.get("content")) + return PlanUpdateRequest(content) def to_dict(self) -> dict: result: dict = {} - if self.sqlite is not None: - result["sqlite"] = from_union([from_bool, from_none], self.sqlite) + result["content"] = from_str(self.content) return result -class SessionFSSetProviderConventions(Enum): - """Path conventions used by this filesystem""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class Plugin: + """Schema for the `Plugin` type.""" - POSIX = "posix" - WINDOWS = "windows" + enabled: bool + """Whether the plugin is currently enabled""" -@dataclass -class SessionFSSetProviderResult: - """Indicates whether the calling client was registered as the session filesystem provider.""" + marketplace: str + """Marketplace the plugin came from""" - success: bool - """Whether the provider was set successfully""" + name: str + """Plugin name""" + + version: str | None = None + """Installed version""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSSetProviderResult': + def from_dict(obj: Any) -> 'Plugin': assert isinstance(obj, dict) - success = from_bool(obj.get("success")) - return SessionFSSetProviderResult(success) + enabled = from_bool(obj.get("enabled")) + marketplace = from_str(obj.get("marketplace")) + name = from_str(obj.get("name")) + version = from_union([from_str, from_none], obj.get("version")) + return Plugin(enabled, marketplace, name, version) def to_dict(self) -> dict: result: dict = {} - result["success"] = from_bool(self.success) + result["enabled"] = from_bool(self.enabled) + result["marketplace"] = from_str(self.marketplace) + result["name"] = from_str(self.name) + if self.version is not None: + 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. +class QueuePendingItemsKind(Enum): + """Whether this item is a queued user message or a queued slash command / model change""" + + COMMAND = "command" + MESSAGE = "message" + +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionFSSqliteExistsRequest: - """Identifies the target session.""" +class QueueRemoveMostRecentResult: + """Indicates whether a user-facing pending item was removed.""" - session_id: str - """Target session identifier""" + removed: bool + """True if a user-facing pending item was removed (LIFO across both queues); false when no + removable items remained. + """ @staticmethod - def from_dict(obj: Any) -> 'SessionFSSqliteExistsRequest': + def from_dict(obj: Any) -> 'QueueRemoveMostRecentResult': assert isinstance(obj, dict) - session_id = from_str(obj.get("sessionId")) - return SessionFSSqliteExistsRequest(session_id) + removed = from_bool(obj.get("removed")) + return QueueRemoveMostRecentResult(removed) def to_dict(self) -> dict: result: dict = {} - result["sessionId"] = from_str(self.session_id) + result["removed"] = from_bool(self.removed) return result @dataclass -class SessionFSSqliteExistsResult: - """Indicates whether the per-session SQLite database already exists.""" +class QueuedCommandHandled: + """Schema for the `QueuedCommandHandled` type.""" - exists: bool - """Whether the session database already exists""" + handled: bool + """The host actually executed the queued command.""" + + stop_processing_queue: bool | None = None + """When true, the runtime will not process subsequent queued commands until a new request + comes in. + """ @staticmethod - def from_dict(obj: Any) -> 'SessionFSSqliteExistsResult': + def from_dict(obj: Any) -> 'QueuedCommandHandled': assert isinstance(obj, dict) - exists = from_bool(obj.get("exists")) - return SessionFSSqliteExistsResult(exists) + handled = from_bool(obj.get("handled")) + stop_processing_queue = from_union([from_bool, from_none], obj.get("stopProcessingQueue")) + return QueuedCommandHandled(handled, stop_processing_queue) def to_dict(self) -> dict: result: dict = {} - result["exists"] = from_bool(self.exists) + result["handled"] = from_bool(self.handled) + if self.stop_processing_queue is not None: + result["stopProcessingQueue"] = from_union([from_bool, from_none], self.stop_processing_queue) return result -class SessionFSSqliteQueryType(Enum): - """How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT - (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) - """ - EXEC = "exec" - QUERY = "query" - RUN = "run" - @dataclass -class SessionFSStatRequest: - """Path whose metadata should be returned from the client-provided session filesystem.""" - - path: str - """Path using SessionFs conventions""" +class QueuedCommandNotHandled: + """Schema for the `QueuedCommandNotHandled` type.""" - session_id: str - """Target session identifier""" + handled: bool + """The host did not execute the queued command. Unblocks the queue without claiming the + command was processed (e.g. when the handler threw before completing). + """ @staticmethod - def from_dict(obj: Any) -> 'SessionFSStatRequest': + def from_dict(obj: Any) -> 'QueuedCommandNotHandled': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - session_id = from_str(obj.get("sessionId")) - return SessionFSStatRequest(path, session_id) + handled = from_bool(obj.get("handled")) + return QueuedCommandNotHandled(handled) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) + result["handled"] = from_bool(self.handled) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionFSWriteFileRequest: - """File path, content to write, and optional mode for the client-provided session filesystem.""" +class RegisterEventInterestParams: + """Event type to register consumer interest for, used by runtime gating logic.""" + + event_type: str + """The event type the consumer wants the runtime to treat as 'observed' for + behavior-switching gating. Some runtime code paths inspect whether any consumer is + interested in a specific event type and choose a different implementation accordingly + (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full + interactive OAuth flow to the consumer; when no interest is registered the runtime + installs a browserless fallback that silently reuses cached tokens). SDK clients that + long-poll events do NOT automatically appear as listeners to these gating checks — they + must explicitly call `registerInterest` for each event type they want the runtime to + count as having a consumer. Multiple registrations for the same event type from the same + or different consumers are tracked independently and must each be released. See: + `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, + `user_input.requested`, `elicitation.requested`, `command.queued`, + `exit_plan_mode.requested`. + """ - content: str - """Content to write""" + @staticmethod + def from_dict(obj: Any) -> 'RegisterEventInterestParams': + assert isinstance(obj, dict) + event_type = from_str(obj.get("eventType")) + return RegisterEventInterestParams(event_type) - path: str - """Path using SessionFs conventions""" + def to_dict(self) -> dict: + result: dict = {} + result["eventType"] = from_str(self.event_type) + return result - session_id: str - """Target session identifier""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class RegisterEventInterestResult: + """Opaque handle representing an event-type interest registration.""" - mode: int | None = None - """Optional POSIX-style mode for newly created files""" + handle: str + """Opaque handle for this registration. Pass to releaseInterest to release. Each call to + registerInterest produces a fresh handle, even when the same eventType is registered + multiple times. + """ @staticmethod - def from_dict(obj: Any) -> 'SessionFSWriteFileRequest': + def from_dict(obj: Any) -> 'RegisterEventInterestResult': 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_int, from_none], obj.get("mode")) - return SessionFSWriteFileRequest(content, path, session_id, mode) + handle = from_str(obj.get("handle")) + return RegisterEventInterestResult(handle) def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) - result["path"] = from_str(self.path) - result["sessionId"] = from_str(self.session_id) - if self.mode is not None: - result["mode"] = from_union([from_int, from_none], self.mode) + result["handle"] = from_str(self.handle) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionsForkRequest: - """Source session identifier to fork from, optional event-ID boundary, and optional friendly - name for the new session. - """ - session_id: str - """Source session ID to fork from""" - - name: str | None = None - """Optional friendly name to assign to the forked session.""" - - to_event_id: str | None = None - """Optional event ID boundary. When provided, the fork includes only events before this ID - (exclusive). When omitted, all events are included. +class ReleaseEventInterestParams: + """Opaque handle previously returned by `registerInterest` to release.""" + + handle: str + """Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown + or already-released handle is a no-op (returns success). When the last outstanding handle + for an event type is released, the runtime reverts to its 'no consumer' code path for + that event type. """ @staticmethod - def from_dict(obj: Any) -> 'SessionsForkRequest': + def from_dict(obj: Any) -> 'ReleaseEventInterestParams': assert isinstance(obj, dict) - session_id = from_str(obj.get("sessionId")) - name = from_union([from_str, from_none], obj.get("name")) - to_event_id = from_union([from_str, from_none], obj.get("toEventId")) - return SessionsForkRequest(session_id, name, to_event_id) + handle = from_str(obj.get("handle")) + return ReleaseEventInterestParams(handle) def to_dict(self) -> dict: result: dict = {} - result["sessionId"] = from_str(self.session_id) - if self.name is not None: - result["name"] = from_union([from_str, from_none], self.name) - if self.to_event_id is not None: - result["toEventId"] = from_union([from_str, from_none], self.to_event_id) + result["handle"] = from_str(self.handle) return result +# Experimental: this type is part of an experimental API and may change or be removed. +class RemoteSessionMode(Enum): + """Per-session remote mode. "off" disables remote, "export" exports session events to GitHub + without enabling remote steering, "on" enables both export and remote steering. + """ + EXPORT = "export" + OFF = "off" + ON = "on" + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionsForkResult: - """Identifier and optional friendly name assigned to the newly forked session.""" +class RemoteEnableResult: + """GitHub URL for the session and a flag indicating whether remote steering is enabled.""" - session_id: str - """The new forked session's ID""" + remote_steerable: bool + """Whether remote steering is enabled""" - name: str | None = None - """Friendly name assigned to the forked session, if any.""" + url: str | None = None + """GitHub frontend URL for this session""" @staticmethod - def from_dict(obj: Any) -> 'SessionsForkResult': + def from_dict(obj: Any) -> 'RemoteEnableResult': assert isinstance(obj, dict) - session_id = from_str(obj.get("sessionId")) - name = from_union([from_str, from_none], obj.get("name")) - return SessionsForkResult(session_id, name) + remote_steerable = from_bool(obj.get("remoteSteerable")) + url = from_union([from_str, from_none], obj.get("url")) + return RemoteEnableResult(remote_steerable, url) def to_dict(self) -> dict: result: dict = {} - result["sessionId"] = from_str(self.session_id) - if self.name is not None: - result["name"] = from_union([from_str, from_none], self.name) + result["remoteSteerable"] = from_bool(self.remote_steerable) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ShellExecRequest: - """Shell command to run, with optional working directory and timeout in milliseconds.""" - - command: str - """Shell command to execute""" - - cwd: str | None = None - """Working directory (defaults to session working directory)""" +class RemoteNotifySteerableChangedRequest: + """New remote-steerability state to persist as a `session.remote_steerable_changed` event.""" - timeout: int | None = None - """Timeout in milliseconds (default: 30000)""" + remote_steerable: bool + """Whether the session now supports remote steering via GitHub. The runtime persists this as + a `session.remote_steerable_changed` event so resume/replay sees the up-to-date + capability. + """ @staticmethod - def from_dict(obj: Any) -> 'ShellExecRequest': + def from_dict(obj: Any) -> 'RemoteNotifySteerableChangedRequest': assert isinstance(obj, dict) - command = from_str(obj.get("command")) - cwd = from_union([from_str, from_none], obj.get("cwd")) - timeout = from_union([from_int, from_none], obj.get("timeout")) - return ShellExecRequest(command, cwd, timeout) - - def to_dict(self) -> dict: - result: dict = {} - result["command"] = from_str(self.command) - if self.cwd is not None: - result["cwd"] = from_union([from_str, from_none], self.cwd) - if self.timeout is not None: - result["timeout"] = from_union([from_int, from_none], self.timeout) - return result - -@dataclass -class ShellExecResult: - """Identifier of the spawned process, used to correlate streamed output and exit - notifications. - """ - process_id: str - """Unique identifier for tracking streamed output""" - - @staticmethod - def from_dict(obj: Any) -> 'ShellExecResult': - assert isinstance(obj, dict) - process_id = from_str(obj.get("processId")) - return ShellExecResult(process_id) + remote_steerable = from_bool(obj.get("remoteSteerable")) + return RemoteNotifySteerableChangedRequest(remote_steerable) def to_dict(self) -> dict: result: dict = {} - result["processId"] = from_str(self.process_id) + result["remoteSteerable"] = from_bool(self.remote_steerable) return result -class ShellKillSignal(Enum): - """Signal to send (default: SIGTERM)""" - - SIGINT = "SIGINT" - SIGKILL = "SIGKILL" - SIGTERM = "SIGTERM" - +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ShellKillResult: - """Indicates whether the signal was delivered; false if the process was unknown or already - exited. +class RemoteNotifySteerableChangedResult: + """Persist a steerability change as a `session.remote_steerable_changed` event. Used by the + host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a + remote exporter that the runtime does not directly own. """ - killed: bool - """Whether the signal was sent successfully""" - @staticmethod - def from_dict(obj: Any) -> 'ShellKillResult': + def from_dict(obj: Any) -> 'RemoteNotifySteerableChangedResult': assert isinstance(obj, dict) - killed = from_bool(obj.get("killed")) - return ShellKillResult(killed) + return RemoteNotifySteerableChangedResult() def to_dict(self) -> dict: result: dict = {} - result["killed"] = from_bool(self.killed) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class Skill: - """Schema for the `Skill` type.""" - - description: str - """Description of what the skill does""" +class ScheduleEntry: + """Schema for the `ScheduleEntry` type. - enabled: bool - """Whether the skill is currently enabled""" + The removed entry, or omitted if no entry matched. + """ + id: int + """Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt + from the event log). + """ + interval_ms: int + """Interval between scheduled ticks, in milliseconds.""" - name: str - """Unique identifier for the skill""" + next_run_at: datetime + """ISO 8601 timestamp when the next tick is scheduled to fire.""" - source: SkillSource - """Source location type (e.g., project, personal-copilot, plugin, builtin)""" + prompt: str + """Prompt text that gets enqueued on every tick.""" - user_invocable: bool - """Whether the skill can be invoked by the user as a slash command""" + recurring: bool + """Whether the schedule re-arms after each tick (`/every`) or fires once (`/after`).""" - path: str | None = None - """Absolute path to the skill file""" + display_prompt: str | None = None + """Display-only label for the prompt as shown in the UI (e.g. `/skill-name` for a + skill-invocation schedule). The actual enqueued prompt is `prompt`. + """ @staticmethod - def from_dict(obj: Any) -> 'Skill': + def from_dict(obj: Any) -> 'ScheduleEntry': assert isinstance(obj, dict) - description = from_str(obj.get("description")) - enabled = from_bool(obj.get("enabled")) - name = from_str(obj.get("name")) - source = SkillSource(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) + id = from_int(obj.get("id")) + interval_ms = from_int(obj.get("intervalMs")) + next_run_at = from_datetime(obj.get("nextRunAt")) + prompt = from_str(obj.get("prompt")) + recurring = from_bool(obj.get("recurring")) + display_prompt = from_union([from_str, from_none], obj.get("displayPrompt")) + return ScheduleEntry(id, interval_ms, next_run_at, prompt, recurring, display_prompt) def to_dict(self) -> dict: result: dict = {} - result["description"] = from_str(self.description) - result["enabled"] = from_bool(self.enabled) - result["name"] = from_str(self.name) - result["source"] = to_enum(SkillSource, self.source) - result["userInvocable"] = from_bool(self.user_invocable) - if self.path is not None: - result["path"] = from_union([from_str, from_none], self.path) + result["id"] = from_int(self.id) + result["intervalMs"] = from_int(self.interval_ms) + result["nextRunAt"] = self.next_run_at.isoformat() + result["prompt"] = from_str(self.prompt) + result["recurring"] = from_bool(self.recurring) + if self.display_prompt is not None: + result["displayPrompt"] = from_union([from_str, from_none], self.display_prompt) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SkillsDisableRequest: - """Name of the skill to disable for the session.""" +class ScheduleStopRequest: + """Identifier of the scheduled prompt to remove.""" - name: str - """Name of the skill to disable""" + id: int + """Id of the scheduled prompt to remove.""" @staticmethod - def from_dict(obj: Any) -> 'SkillsDisableRequest': + def from_dict(obj: Any) -> 'ScheduleStopRequest': assert isinstance(obj, dict) - name = from_str(obj.get("name")) - return SkillsDisableRequest(name) + id = from_int(obj.get("id")) + return ScheduleStopRequest(id) def to_dict(self) -> dict: result: dict = {} - result["name"] = from_str(self.name) + result["id"] = from_int(self.id) return result +class SendAgentMode(Enum): + """The UI mode the agent was in when this message was sent. Defaults to the session's + current mode. + """ + AUTOPILOT = "autopilot" + INTERACTIVE = "interactive" + PLAN = "plan" + SHELL = "shell" + @dataclass -class SkillsDiscoverRequest: - """Optional project paths and additional skill directories to include in discovery.""" +class SendAttachmentFileLineRange: + """Optional line range to scope the attachment to a specific section of the file""" - project_paths: list[str] | None = None - """Optional list of project directory paths to scan for project-scoped skills""" + end: int + """End line number (1-based, inclusive)""" - skill_directories: list[str] | None = None - """Optional list of additional skill directory paths to include""" + start: int + """Start line number (1-based)""" @staticmethod - def from_dict(obj: Any) -> 'SkillsDiscoverRequest': + def from_dict(obj: Any) -> 'SendAttachmentFileLineRange': assert isinstance(obj, dict) - project_paths = from_union([lambda x: from_list(from_str, x), from_none], obj.get("projectPaths")) - skill_directories = from_union([lambda x: from_list(from_str, x), from_none], obj.get("skillDirectories")) - return SkillsDiscoverRequest(project_paths, skill_directories) + end = from_int(obj.get("end")) + start = from_int(obj.get("start")) + return SendAttachmentFileLineRange(end, start) def to_dict(self) -> dict: result: dict = {} - if self.project_paths is not None: - result["projectPaths"] = from_union([lambda x: from_list(from_str, x), from_none], self.project_paths) - if self.skill_directories is not None: - result["skillDirectories"] = from_union([lambda x: from_list(from_str, x), from_none], self.skill_directories) + result["end"] = from_int(self.end) + result["start"] = from_int(self.start) return result -# Experimental: this type is part of an experimental API and may change or be removed. +class SendAttachmentGithubReferenceTypeEnum(Enum): + """Type of GitHub reference""" + + DISCUSSION = "discussion" + ISSUE = "issue" + PR = "pr" + @dataclass -class SkillsEnableRequest: - """Name of the skill to enable for the session.""" +class SendAttachmentSelectionDetailsEnd: + """End position of the selection""" - name: str - """Name of the skill to enable""" + character: int + """End character offset within the line (0-based)""" + + line: int + """End line number (0-based)""" @staticmethod - def from_dict(obj: Any) -> 'SkillsEnableRequest': + def from_dict(obj: Any) -> 'SendAttachmentSelectionDetailsEnd': assert isinstance(obj, dict) - name = from_str(obj.get("name")) - return SkillsEnableRequest(name) + character = from_int(obj.get("character")) + line = from_int(obj.get("line")) + return SendAttachmentSelectionDetailsEnd(character, line) def to_dict(self) -> dict: result: dict = {} - result["name"] = from_str(self.name) + result["character"] = from_int(self.character) + result["line"] = from_int(self.line) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SkillsLoadDiagnostics: - """Diagnostics from reloading skill definitions, with warnings and errors as separate lists.""" +class SendAttachmentSelectionDetailsStart: + """Start position of the selection""" - errors: list[str] - """Errors emitted while loading skills (e.g. skills that failed to load entirely)""" + character: int + """Start character offset within the line (0-based)""" - warnings: list[str] - """Warnings emitted while loading skills (e.g. skills that loaded but had issues)""" + line: int + """Start line number (0-based)""" @staticmethod - def from_dict(obj: Any) -> 'SkillsLoadDiagnostics': + def from_dict(obj: Any) -> 'SendAttachmentSelectionDetailsStart': assert isinstance(obj, dict) - errors = from_list(from_str, obj.get("errors")) - warnings = from_list(from_str, obj.get("warnings")) - return SkillsLoadDiagnostics(errors, warnings) + character = from_int(obj.get("character")) + line = from_int(obj.get("line")) + return SendAttachmentSelectionDetailsStart(character, line) def to_dict(self) -> dict: result: dict = {} - result["errors"] = from_list(from_str, self.errors) - result["warnings"] = from_list(from_str, self.warnings) + result["character"] = from_int(self.character) + result["line"] = from_int(self.line) return result -class SlashCommandAgentPromptResultKind(Enum): - AGENT_PROMPT = "agent-prompt" - -class SlashCommandCompletedResultKind(Enum): - COMPLETED = "completed" - -class SlashCommandInvocationResultKind(Enum): - AGENT_PROMPT = "agent-prompt" - COMPLETED = "completed" - TEXT = "text" - -# Experimental: this type is part of an experimental API and may change or be removed. -class TaskExecutionMode(Enum): - """Whether task execution is synchronously awaited or managed in the background""" +class SendAttachmentType(Enum): + BLOB = "blob" + DIRECTORY = "directory" + FILE = "file" + GITHUB_REFERENCE = "github_reference" + SELECTION = "selection" - BACKGROUND = "background" - SYNC = "sync" +class SendAttachmentBlobType(Enum): + BLOB = "blob" -# Experimental: this type is part of an experimental API and may change or be removed. -class TaskStatus(Enum): - """Current lifecycle status of the task""" +class SendAttachmentFileType(Enum): + FILE = "file" - CANCELLED = "cancelled" - COMPLETED = "completed" - FAILED = "failed" - IDLE = "idle" - RUNNING = "running" +class SendAttachmentGithubReferenceType(Enum): + GITHUB_REFERENCE = "github_reference" -class TaskAgentInfoType(Enum): - AGENT = "agent" +class SendAttachmentSelectionType(Enum): + SELECTION = "selection" -# Experimental: this type is part of an experimental API and may change or be removed. -class TaskShellInfoAttachmentMode(Enum): - """Whether the shell runs inside a managed PTY session or as an independent background - process +class SendMode(Enum): + """How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` + interjects during an in-progress turn. """ - ATTACHED = "attached" - DETACHED = "detached" - -class TaskInfoType(Enum): - AGENT = "agent" - SHELL = "shell" - -class TaskShellInfoType(Enum): - SHELL = "shell" + ENQUEUE = "enqueue" + IMMEDIATE = "immediate" -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksCancelRequest: - """Identifier of the background task to cancel.""" +class SendResult: + """Result of sending a user message""" - id: str - """Task identifier""" + message_id: str + """Unique identifier assigned to the message""" @staticmethod - def from_dict(obj: Any) -> 'TasksCancelRequest': + def from_dict(obj: Any) -> 'SendResult': assert isinstance(obj, dict) - id = from_str(obj.get("id")) - return TasksCancelRequest(id) + message_id = from_str(obj.get("messageId")) + return SendResult(message_id) def to_dict(self) -> dict: result: dict = {} - result["id"] = from_str(self.id) + result["messageId"] = from_str(self.message_id) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksCancelResult: - """Indicates whether the background task was successfully cancelled.""" +class ServerSkill: + """Schema for the `ServerSkill` type.""" - cancelled: bool - """Whether the task was successfully cancelled""" + description: str + """Description of what the skill does""" - @staticmethod - def from_dict(obj: Any) -> 'TasksCancelResult': - assert isinstance(obj, dict) - cancelled = from_bool(obj.get("cancelled")) - return TasksCancelResult(cancelled) + enabled: bool + """Whether the skill is currently enabled (based on global config)""" - def to_dict(self) -> dict: - result: dict = {} - result["cancelled"] = from_bool(self.cancelled) - return result + name: str + """Unique identifier for the skill""" -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class TasksPromoteToBackgroundRequest: - """Identifier of the task to promote to background mode.""" + source: SkillSource + """Source location type (e.g., project, personal-copilot, plugin, builtin)""" - id: str - """Task identifier""" + user_invocable: bool + """Whether the skill can be invoked by the user as a slash command""" + + path: str | None = None + """Absolute path to the skill file""" + + project_path: str | None = None + """The project path this skill belongs to (only for project/inherited skills)""" @staticmethod - def from_dict(obj: Any) -> 'TasksPromoteToBackgroundRequest': + def from_dict(obj: Any) -> 'ServerSkill': assert isinstance(obj, dict) - id = from_str(obj.get("id")) - return TasksPromoteToBackgroundRequest(id) + description = from_str(obj.get("description")) + enabled = from_bool(obj.get("enabled")) + name = from_str(obj.get("name")) + source = SkillSource(obj.get("source")) + user_invocable = from_bool(obj.get("userInvocable")) + path = from_union([from_str, from_none], obj.get("path")) + project_path = from_union([from_str, from_none], obj.get("projectPath")) + return ServerSkill(description, enabled, name, source, user_invocable, path, project_path) def to_dict(self) -> dict: result: dict = {} - result["id"] = from_str(self.id) + result["description"] = from_str(self.description) + result["enabled"] = from_bool(self.enabled) + result["name"] = from_str(self.name) + result["source"] = to_enum(SkillSource, self.source) + result["userInvocable"] = from_bool(self.user_invocable) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.project_path is not None: + result["projectPath"] = from_union([from_str, from_none], self.project_path) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksPromoteToBackgroundResult: - """Indicates whether the task was successfully promoted to background mode.""" +class SessionBulkDeleteResult: + """Map of sessionId -> bytes freed by removing the session's workspace directory.""" - promoted: bool - """Whether the task was successfully promoted to background mode""" + freed_bytes: dict[str, int] + """Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions + whose deletion failed are omitted from this map (failures are logged on the server but + not surfaced per-id; check the map for absent IDs to detect them). + """ @staticmethod - def from_dict(obj: Any) -> 'TasksPromoteToBackgroundResult': + def from_dict(obj: Any) -> 'SessionBulkDeleteResult': assert isinstance(obj, dict) - promoted = from_bool(obj.get("promoted")) - return TasksPromoteToBackgroundResult(promoted) + freed_bytes = from_dict(from_int, obj.get("freedBytes")) + return SessionBulkDeleteResult(freed_bytes) def to_dict(self) -> dict: result: dict = {} - result["promoted"] = from_bool(self.promoted) + result["freedBytes"] = from_dict(from_int, self.freed_bytes) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksRemoveRequest: - """Identifier of the completed or cancelled task to remove from tracking.""" - - id: str - """Task identifier""" +class SessionFSAppendFileRequest: + """File path, content to append, and optional mode for the client-provided session + filesystem. + """ + content: str + """Content to append""" - @staticmethod - def from_dict(obj: Any) -> 'TasksRemoveRequest': - assert isinstance(obj, dict) - id = from_str(obj.get("id")) - return TasksRemoveRequest(id) + path: str + """Path using SessionFs conventions""" - def to_dict(self) -> dict: - result: dict = {} - result["id"] = from_str(self.id) - return result + session_id: str + """Target session identifier""" -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class TasksRemoveResult: - """Indicates whether the task was removed. False when the task does not exist or is still - running/idle. - """ - removed: bool - """Whether the task was removed. Returns false if the task does not exist or is still - running/idle (cancel it first). - """ + mode: int | None = None + """Optional POSIX-style mode for newly created files""" @staticmethod - def from_dict(obj: Any) -> 'TasksRemoveResult': + def from_dict(obj: Any) -> 'SessionFSAppendFileRequest': assert isinstance(obj, dict) - removed = from_bool(obj.get("removed")) - return TasksRemoveResult(removed) + content = from_str(obj.get("content")) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + mode = from_union([from_int, from_none], obj.get("mode")) + return SessionFSAppendFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} - result["removed"] = from_bool(self.removed) + result["content"] = from_str(self.content) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) + if self.mode is not None: + result["mode"] = from_union([from_int, from_none], self.mode) return result -# Experimental: this type is part of an experimental API and may change or be removed. -@dataclass -class TasksSendMessageRequest: - """Identifier of the target agent task, message content, and optional sender agent ID.""" +class SessionFSErrorCode(Enum): + """Error classification""" - id: str - """Agent task identifier""" + ENOENT = "ENOENT" + UNKNOWN = "UNKNOWN" - message: str - """Message content to send to the agent""" +@dataclass +class SessionFSExistsRequest: + """Path to test for existence in the client-provided session filesystem.""" - from_agent_id: str | None = None - """Agent ID of the sender, if sent on behalf of another agent""" + path: str + """Path using SessionFs conventions""" + + session_id: str + """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'TasksSendMessageRequest': + def from_dict(obj: Any) -> 'SessionFSExistsRequest': assert isinstance(obj, dict) - id = from_str(obj.get("id")) - message = from_str(obj.get("message")) - from_agent_id = from_union([from_str, from_none], obj.get("fromAgentId")) - return TasksSendMessageRequest(id, message, from_agent_id) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + return SessionFSExistsRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} - result["id"] = from_str(self.id) - result["message"] = from_str(self.message) - if self.from_agent_id is not None: - result["fromAgentId"] = from_union([from_str, from_none], self.from_agent_id) + result["path"] = from_str(self.path) + 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 TasksSendMessageResult: - """Indicates whether the message was delivered, with an error message when delivery failed.""" - - sent: bool - """Whether the message was successfully delivered or steered""" +class SessionFSExistsResult: + """Indicates whether the requested path exists in the client-provided session filesystem.""" - error: str | None = None - """Error message if delivery failed""" + exists: bool + """Whether the path exists""" @staticmethod - def from_dict(obj: Any) -> 'TasksSendMessageResult': + def from_dict(obj: Any) -> 'SessionFSExistsResult': assert isinstance(obj, dict) - sent = from_bool(obj.get("sent")) - error = from_union([from_str, from_none], obj.get("error")) - return TasksSendMessageResult(sent, error) + exists = from_bool(obj.get("exists")) + return SessionFSExistsResult(exists) def to_dict(self) -> dict: result: dict = {} - result["sent"] = from_bool(self.sent) - if self.error is not None: - result["error"] = from_union([from_str, from_none], self.error) + result["exists"] = from_bool(self.exists) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksStartAgentRequest: - """Agent type, prompt, name, and optional description and model override for the new task.""" - - agent_type: str - """Type of agent to start (e.g., 'explore', 'task', 'general-purpose')""" - - name: str - """Short name for the agent, used to generate a human-readable ID""" +class SessionFSMkdirRequest: + """Directory path to create in the client-provided session filesystem, with options for + recursive creation and POSIX mode. + """ + path: str + """Path using SessionFs conventions""" - prompt: str - """Task prompt for the agent""" + session_id: str + """Target session identifier""" - description: str | None = None - """Short description of the task""" + mode: int | None = None + """Optional POSIX-style mode for newly created directories""" - model: str | None = None - """Optional model override""" + recursive: bool | None = None + """Create parent directories as needed""" @staticmethod - def from_dict(obj: Any) -> 'TasksStartAgentRequest': + def from_dict(obj: Any) -> 'SessionFSMkdirRequest': assert isinstance(obj, dict) - agent_type = from_str(obj.get("agentType")) - name = from_str(obj.get("name")) - prompt = from_str(obj.get("prompt")) - description = from_union([from_str, from_none], obj.get("description")) - model = from_union([from_str, from_none], obj.get("model")) - return TasksStartAgentRequest(agent_type, name, prompt, description, model) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + mode = from_union([from_int, from_none], obj.get("mode")) + recursive = from_union([from_bool, from_none], obj.get("recursive")) + return SessionFSMkdirRequest(path, session_id, mode, recursive) def to_dict(self) -> dict: result: dict = {} - result["agentType"] = from_str(self.agent_type) - result["name"] = from_str(self.name) - result["prompt"] = from_str(self.prompt) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) - if self.model is not None: - result["model"] = from_union([from_str, from_none], self.model) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) + if self.mode is not None: + result["mode"] = from_union([from_int, from_none], self.mode) + if self.recursive is not None: + result["recursive"] = from_union([from_bool, from_none], self.recursive) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TasksStartAgentResult: - """Identifier assigned to the newly started background agent task.""" +class SessionFSReadFileRequest: + """Path of the file to read from the client-provided session filesystem.""" - agent_id: str - """Generated agent ID for the background task""" + path: str + """Path using SessionFs conventions""" + + session_id: str + """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'TasksStartAgentResult': + def from_dict(obj: Any) -> 'SessionFSReadFileRequest': assert isinstance(obj, dict) - agent_id = from_str(obj.get("agentId")) - return TasksStartAgentResult(agent_id) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + return SessionFSReadFileRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} - result["agentId"] = from_str(self.agent_id) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) return result @dataclass -class Tool: - """Schema for the `Tool` type.""" - - description: str - """Description of what the tool does""" - - name: str - """Tool identifier (e.g., "bash", "grep", "str_replace_editor")""" +class SessionFSReaddirRequest: + """Directory path whose entries should be listed from the client-provided session filesystem.""" - instructions: str | None = None - """Optional instructions for how to use this tool effectively""" + path: str + """Path using SessionFs conventions""" - namespaced_name: str | None = None - """Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP - tools) - """ - parameters: dict[str, Any] | None = None - """JSON Schema for the tool's input parameters""" + session_id: str + """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'Tool': + def from_dict(obj: Any) -> 'SessionFSReaddirRequest': assert isinstance(obj, dict) - description = from_str(obj.get("description")) - name = from_str(obj.get("name")) - instructions = from_union([from_str, from_none], obj.get("instructions")) - namespaced_name = from_union([from_str, from_none], obj.get("namespacedName")) - parameters = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("parameters")) - return Tool(description, name, instructions, namespaced_name, parameters) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + return SessionFSReaddirRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} - result["description"] = from_str(self.description) - result["name"] = from_str(self.name) - if self.instructions is not None: - result["instructions"] = from_union([from_str, from_none], self.instructions) - if self.namespaced_name is not None: - result["namespacedName"] = from_union([from_str, from_none], self.namespaced_name) - if self.parameters is not None: - result["parameters"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.parameters) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) return result -@dataclass -class ToolsListRequest: - """Optional model identifier whose tool overrides should be applied to the listing.""" +class SessionFSReaddirWithTypesEntryType(Enum): + """Entry type""" - model: str | None = None - """Optional model ID — when provided, the returned tool list reflects model-specific - overrides + DIRECTORY = "directory" + FILE = "file" + +@dataclass +class SessionFSReaddirWithTypesRequest: + """Directory path whose entries (with type information) should be listed from the + client-provided session filesystem. """ + path: str + """Path using SessionFs conventions""" + + session_id: str + """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'ToolsListRequest': + def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesRequest': assert isinstance(obj, dict) - model = from_union([from_str, from_none], obj.get("model")) - return ToolsListRequest(model) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + return SessionFSReaddirWithTypesRequest(path, session_id) def to_dict(self) -> dict: result: dict = {} - if self.model is not None: - result["model"] = from_union([from_str, from_none], self.model) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) return result @dataclass -class UIElicitationArrayAnyOfFieldItemsAnyOf: - """Schema for the `UIElicitationArrayAnyOfFieldItemsAnyOf` type.""" +class SessionFSRenameRequest: + """Source and destination paths for renaming or moving an entry in the client-provided + session filesystem. + """ + dest: str + """Destination path using SessionFs conventions""" - const: str - """Value submitted when this option is selected.""" + session_id: str + """Target session identifier""" - title: str - """Display label for this option.""" + src: str + """Source path using SessionFs conventions""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItemsAnyOf': + def from_dict(obj: Any) -> 'SessionFSRenameRequest': assert isinstance(obj, dict) - const = from_str(obj.get("const")) - title = from_str(obj.get("title")) - return UIElicitationArrayAnyOfFieldItemsAnyOf(const, title) + dest = from_str(obj.get("dest")) + session_id = from_str(obj.get("sessionId")) + src = from_str(obj.get("src")) + return SessionFSRenameRequest(dest, session_id, src) def to_dict(self) -> dict: result: dict = {} - result["const"] = from_str(self.const) - result["title"] = from_str(self.title) + result["dest"] = from_str(self.dest) + result["sessionId"] = from_str(self.session_id) + result["src"] = from_str(self.src) return result -class UIElicitationArrayAnyOfFieldType(Enum): - ARRAY = "array" - -class UIElicitationArrayEnumFieldItemsType(Enum): - STRING = "string" - -class UIElicitationSchemaPropertyStringFormat(Enum): - """Optional format hint that constrains the accepted input.""" - - DATE = "date" - DATE_TIME = "date-time" - EMAIL = "email" - URI = "uri" - @dataclass -class UIElicitationStringOneOfFieldOneOf: - """Schema for the `UIElicitationStringOneOfFieldOneOf` type.""" +class SessionFSRmRequest: + """Path to remove from the client-provided session filesystem, with options for recursive + removal and force. + """ + path: str + """Path using SessionFs conventions""" - const: str - """Value submitted when this option is selected.""" + session_id: str + """Target session identifier""" - title: str - """Display label for this option.""" + force: bool | None = None + """Ignore errors if the path does not exist""" + + recursive: bool | None = None + """Remove directories and their contents recursively""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationStringOneOfFieldOneOf': + def from_dict(obj: Any) -> 'SessionFSRmRequest': assert isinstance(obj, dict) - const = from_str(obj.get("const")) - title = from_str(obj.get("title")) - return UIElicitationStringOneOfFieldOneOf(const, title) + 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 SessionFSRmRequest(path, session_id, force, recursive) def to_dict(self) -> dict: result: dict = {} - result["const"] = from_str(self.const) - result["title"] = from_str(self.title) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) + if self.force is not None: + result["force"] = from_union([from_bool, from_none], self.force) + if self.recursive is not None: + result["recursive"] = from_union([from_bool, from_none], self.recursive) return result -class UIElicitationSchemaPropertyType(Enum): - """Numeric type accepted by the field.""" +@dataclass +class SessionFSSetProviderCapabilities: + """Optional capabilities declared by the provider""" - ARRAY = "array" - BOOLEAN = "boolean" - INTEGER = "integer" - NUMBER = "number" - STRING = "string" + sqlite: bool | None = None + """Whether the provider supports SQLite query/exists operations""" -class UIElicitationSchemaType(Enum): - OBJECT = "object" + @staticmethod + def from_dict(obj: Any) -> 'SessionFSSetProviderCapabilities': + assert isinstance(obj, dict) + sqlite = from_union([from_bool, from_none], obj.get("sqlite")) + return SessionFSSetProviderCapabilities(sqlite) -class UIElicitationResponseAction(Enum): - """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" + def to_dict(self) -> dict: + result: dict = {} + if self.sqlite is not None: + result["sqlite"] = from_union([from_bool, from_none], self.sqlite) + return result - ACCEPT = "accept" - CANCEL = "cancel" - DECLINE = "decline" +class SessionFSSetProviderConventions(Enum): + """Path conventions used by this filesystem""" + + POSIX = "posix" + WINDOWS = "windows" @dataclass -class UIElicitationResult: - """Indicates whether the elicitation response was accepted; false if it was already resolved - by another client. - """ +class SessionFSSetProviderResult: + """Indicates whether the calling client was registered as the session filesystem provider.""" + success: bool - """Whether the response was accepted. False if the request was already resolved by another - client. - """ + """Whether the provider was set successfully""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationResult': + def from_dict(obj: Any) -> 'SessionFSSetProviderResult': assert isinstance(obj, dict) success = from_bool(obj.get("success")) - return UIElicitationResult(success) + return SessionFSSetProviderResult(success) def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) return result -class UIElicitationSchemaPropertyBooleanType(Enum): - BOOLEAN = "boolean" +@dataclass +class SessionFSSqliteExistsRequest: + """Identifies the target session.""" -class UIElicitationSchemaPropertyNumberType(Enum): - """Numeric type accepted by the field.""" + session_id: str + """Target session identifier""" - INTEGER = "integer" - NUMBER = "number" + @staticmethod + def from_dict(obj: Any) -> 'SessionFSSqliteExistsRequest': + assert isinstance(obj, dict) + session_id = from_str(obj.get("sessionId")) + return SessionFSSqliteExistsRequest(session_id) + + def to_dict(self) -> dict: + result: 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 UsageMetricsCodeChanges: - """Aggregated code change metrics""" +class SessionFSSqliteExistsResult: + """Indicates whether the per-session SQLite database already exists.""" - files_modified_count: int - """Number of distinct files modified""" + exists: bool + """Whether the session database already exists""" - lines_added: int - """Total lines of code added""" + @staticmethod + def from_dict(obj: Any) -> 'SessionFSSqliteExistsResult': + assert isinstance(obj, dict) + exists = from_bool(obj.get("exists")) + return SessionFSSqliteExistsResult(exists) - lines_removed: int - """Total lines of code removed""" + def to_dict(self) -> dict: + result: dict = {} + result["exists"] = from_bool(self.exists) + return result + +class SessionFSSqliteQueryType(Enum): + """How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT + (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) + """ + EXEC = "exec" + QUERY = "query" + RUN = "run" + +@dataclass +class SessionFSStatRequest: + """Path whose metadata should be returned from the client-provided session filesystem.""" + + path: str + """Path using SessionFs conventions""" + + session_id: str + """Target session identifier""" @staticmethod - def from_dict(obj: Any) -> 'UsageMetricsCodeChanges': + def from_dict(obj: Any) -> 'SessionFSStatRequest': 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) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + return SessionFSStatRequest(path, session_id) 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) + result["path"] = from_str(self.path) + 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 UsageMetricsModelMetricRequests: - """Request count and cost metrics for this model""" +class SessionFSWriteFileRequest: + """File path, content to write, and optional mode for the client-provided session filesystem.""" - cost: float - """User-initiated premium request cost (with multiplier applied)""" + content: str + """Content to write""" - count: int - """Number of API requests made with this model""" + path: str + """Path using SessionFs conventions""" + + session_id: str + """Target session identifier""" + + mode: int | None = None + """Optional POSIX-style mode for newly created files""" @staticmethod - def from_dict(obj: Any) -> 'UsageMetricsModelMetricRequests': + def from_dict(obj: Any) -> 'SessionFSWriteFileRequest': assert isinstance(obj, dict) - cost = from_float(obj.get("cost")) - count = from_int(obj.get("count")) - return UsageMetricsModelMetricRequests(cost, count) + content = from_str(obj.get("content")) + path = from_str(obj.get("path")) + session_id = from_str(obj.get("sessionId")) + mode = from_union([from_int, from_none], obj.get("mode")) + return SessionFSWriteFileRequest(content, path, session_id, mode) def to_dict(self) -> dict: result: dict = {} - result["cost"] = to_float(self.cost) - result["count"] = from_int(self.count) + result["content"] = from_str(self.content) + result["path"] = from_str(self.path) + result["sessionId"] = from_str(self.session_id) + if self.mode is not None: + result["mode"] = from_union([from_int, from_none], self.mode) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UsageMetricsModelMetricTokenDetail: - """Schema for the `UsageMetricsModelMetricTokenDetail` type.""" +class SessionLoadDeferredRepoHooksResult: + """Queued repo-level startup prompts and the total hook command count after loading.""" - token_count: int - """Accumulated token count for this token type""" + hook_count: int + """Total hook command count (user + plugin + repo) loaded for the session by this call. + Captured atomically with startupPrompts so callers don't need to read a separate counter. + """ + startup_prompts: list[str] + """Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo + configs were pending, or when disableAllHooks is set. + """ @staticmethod - def from_dict(obj: Any) -> 'UsageMetricsModelMetricTokenDetail': + def from_dict(obj: Any) -> 'SessionLoadDeferredRepoHooksResult': assert isinstance(obj, dict) - token_count = from_int(obj.get("tokenCount")) - return UsageMetricsModelMetricTokenDetail(token_count) + hook_count = from_int(obj.get("hookCount")) + startup_prompts = from_list(from_str, obj.get("startupPrompts")) + return SessionLoadDeferredRepoHooksResult(hook_count, startup_prompts) def to_dict(self) -> dict: result: dict = {} - result["tokenCount"] = from_int(self.token_count) + result["hookCount"] = from_int(self.hook_count) + result["startupPrompts"] = from_list(from_str, self.startup_prompts) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UsageMetricsModelMetricUsage: - """Token usage metrics for this model""" - - cache_read_tokens: int - """Total tokens read from prompt cache""" +class SessionPruneResult: + """Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes + freed, and the dry-run flag. + """ + candidates: list[str] + """Session IDs that would be deleted in dry-run mode (always empty otherwise)""" - cache_write_tokens: int - """Total tokens written to prompt cache""" + deleted: list[str] + """Session IDs that were deleted (always empty in dry-run mode)""" - input_tokens: int - """Total input tokens consumed""" + dry_run: bool + """True when no deletions were actually performed""" - output_tokens: int - """Total output tokens produced""" + freed_bytes: int + """Total bytes freed (actual when not dry-run, projected when dry-run)""" - reasoning_tokens: int | None = None - """Total output tokens used for reasoning""" + skipped: list[str] + """Session IDs that were skipped (e.g., named sessions)""" @staticmethod - def from_dict(obj: Any) -> 'UsageMetricsModelMetricUsage': + def from_dict(obj: Any) -> 'SessionPruneResult': 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) + candidates = from_list(from_str, obj.get("candidates")) + deleted = from_list(from_str, obj.get("deleted")) + dry_run = from_bool(obj.get("dryRun")) + freed_bytes = from_int(obj.get("freedBytes")) + skipped = from_list(from_str, obj.get("skipped")) + return SessionPruneResult(candidates, deleted, dry_run, freed_bytes, skipped) 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) + result["candidates"] = from_list(from_str, self.candidates) + result["deleted"] = from_list(from_str, self.deleted) + result["dryRun"] = from_bool(self.dry_run) + result["freedBytes"] = from_int(self.freed_bytes) + result["skipped"] = from_list(from_str, self.skipped) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UsageMetricsTokenDetail: - """Schema for the `UsageMetricsTokenDetail` type.""" +class SessionSetCredentialsResult: + """Indicates whether the credential update succeeded.""" - token_count: int - """Accumulated token count for this token type""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'UsageMetricsTokenDetail': + def from_dict(obj: Any) -> 'SessionSetCredentialsResult': assert isinstance(obj, dict) - token_count = from_int(obj.get("tokenCount")) - return UsageMetricsTokenDetail(token_count) + success = from_bool(obj.get("success")) + return SessionSetCredentialsResult(success) def to_dict(self) -> dict: result: dict = {} - result["tokenCount"] = from_int(self.token_count) + result["success"] = from_bool(self.success) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class WorkspacesCreateFileRequest: - """Relative path and UTF-8 content for the workspace file to create or overwrite.""" - - content: str - """File content to write as a UTF-8 string""" +class SessionSizes: + """Map of sessionId -> on-disk size in bytes for each session's workspace directory.""" - path: str - """Relative path within the workspace files directory""" + sizes: dict[str, int] + """Map of sessionId -> on-disk size in bytes for the session's workspace directory""" @staticmethod - def from_dict(obj: Any) -> 'WorkspacesCreateFileRequest': + def from_dict(obj: Any) -> 'SessionSizes': assert isinstance(obj, dict) - content = from_str(obj.get("content")) - path = from_str(obj.get("path")) - return WorkspacesCreateFileRequest(content, path) + sizes = from_dict(from_int, obj.get("sizes")) + return SessionSizes(sizes) def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) - result["path"] = from_str(self.path) + result["sizes"] = from_dict(from_int, self.sizes) return result -class HostType(Enum): - ADO = "ado" - GITHUB = "github" - +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class WorkspacesListFilesResult: - """Relative paths of files stored in the session workspace files directory.""" +class SessionUpdateOptionsResult: + """Indicates whether the session options patch was applied successfully.""" - files: list[str] - """Relative file paths in the workspace files directory""" + success: bool + """Whether the operation succeeded""" @staticmethod - def from_dict(obj: Any) -> 'WorkspacesListFilesResult': + def from_dict(obj: Any) -> 'SessionUpdateOptionsResult': assert isinstance(obj, dict) - files = from_list(from_str, obj.get("files")) - return WorkspacesListFilesResult(files) + success = from_bool(obj.get("success")) + return SessionUpdateOptionsResult(success) def to_dict(self) -> dict: result: dict = {} - result["files"] = from_list(from_str, self.files) + result["success"] = from_bool(self.success) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class WorkspacesReadFileRequest: - """Relative path of the workspace file to read.""" +class SessionsBulkDeleteRequest: + """Session IDs to close, deactivate, and delete from disk.""" - path: str - """Relative path within the workspace files directory""" + session_ids: list[str] + """Session IDs to close, deactivate, and delete from disk""" @staticmethod - def from_dict(obj: Any) -> 'WorkspacesReadFileRequest': + def from_dict(obj: Any) -> 'SessionsBulkDeleteRequest': assert isinstance(obj, dict) - path = from_str(obj.get("path")) - return WorkspacesReadFileRequest(path) + session_ids = from_list(from_str, obj.get("sessionIds")) + return SessionsBulkDeleteRequest(session_ids) def to_dict(self) -> dict: result: dict = {} - result["path"] = from_str(self.path) + result["sessionIds"] = from_list(from_str, self.session_ids) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class WorkspacesReadFileResult: - """Contents of the requested workspace file as a UTF-8 string.""" +class SessionsCheckInUseRequest: + """Session IDs to test for live in-use locks.""" - content: str - """File content as a UTF-8 string""" + session_ids: list[str] + """Session IDs to test for live in-use locks""" @staticmethod - def from_dict(obj: Any) -> 'WorkspacesReadFileResult': + def from_dict(obj: Any) -> 'SessionsCheckInUseRequest': assert isinstance(obj, dict) - content = from_str(obj.get("content")) - return WorkspacesReadFileResult(content) + session_ids = from_list(from_str, obj.get("sessionIds")) + return SessionsCheckInUseRequest(session_ids) def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) + result["sessionIds"] = from_list(from_str, self.session_ids) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AccountGetQuotaResult: - """Quota usage snapshots for the resolved user, keyed by quota type.""" +class SessionsCheckInUseResult: + """Session IDs from the input set that are currently in use by another process.""" - quota_snapshots: dict[str, AccountQuotaSnapshot] - """Quota snapshots keyed by type (e.g., chat, completions, premium_interactions)""" + in_use: list[str] + """Session IDs from the input set that are currently held by another running process via an + alive lock file + """ @staticmethod - def from_dict(obj: Any) -> 'AccountGetQuotaResult': + def from_dict(obj: Any) -> 'SessionsCheckInUseResult': assert isinstance(obj, dict) - quota_snapshots = from_dict(AccountQuotaSnapshot.from_dict, obj.get("quotaSnapshots")) - return AccountGetQuotaResult(quota_snapshots) + in_use = from_list(from_str, obj.get("inUse")) + return SessionsCheckInUseResult(in_use) def to_dict(self) -> dict: result: dict = {} - result["quotaSnapshots"] = from_dict(lambda x: to_class(AccountQuotaSnapshot, x), self.quota_snapshots) + result["inUse"] = from_list(from_str, self.in_use) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AgentGetCurrentResult: - """The currently selected custom agent, or null when using the default agent.""" +class SessionsCloseRequest: + """Session ID to close.""" - agent: AgentInfo | None = None - """Currently selected custom agent, or null if using the default agent""" + session_id: str + """Session ID to close""" @staticmethod - def from_dict(obj: Any) -> 'AgentGetCurrentResult': + def from_dict(obj: Any) -> 'SessionsCloseRequest': assert isinstance(obj, dict) - agent = from_union([AgentInfo.from_dict, from_none], obj.get("agent")) - return AgentGetCurrentResult(agent) + session_id = from_str(obj.get("sessionId")) + return SessionsCloseRequest(session_id) def to_dict(self) -> dict: result: dict = {} - if self.agent is not None: - result["agent"] = from_union([lambda x: to_class(AgentInfo, x), from_none], self.agent) + 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 AgentList: - """Custom agents available to the session.""" - - agents: list[AgentInfo] - """Available custom agents""" - +class SessionsCloseResult: + """Closes a session: emits shutdown, flushes pending events to disk, releases the in-use + lock, disposes the active session. Idempotent: succeeds even if the session is not + currently active. + """ @staticmethod - def from_dict(obj: Any) -> 'AgentList': + def from_dict(obj: Any) -> 'SessionsCloseResult': assert isinstance(obj, dict) - agents = from_list(AgentInfo.from_dict, obj.get("agents")) - return AgentList(agents) + return SessionsCloseResult() def to_dict(self) -> dict: result: dict = {} - result["agents"] = from_list(lambda x: to_class(AgentInfo, x), self.agents) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AgentReloadResult: - """Custom agents available to the session after reloading definitions from disk.""" +class SessionsFindByPrefixRequest: + """UUID prefix to resolve to a unique session ID.""" - agents: list[AgentInfo] - """Reloaded custom agents""" + prefix: str + """UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when + there is no match or the prefix matches multiple sessions. + """ @staticmethod - def from_dict(obj: Any) -> 'AgentReloadResult': + def from_dict(obj: Any) -> 'SessionsFindByPrefixRequest': assert isinstance(obj, dict) - agents = from_list(AgentInfo.from_dict, obj.get("agents")) - return AgentReloadResult(agents) + prefix = from_str(obj.get("prefix")) + return SessionsFindByPrefixRequest(prefix) def to_dict(self) -> dict: result: dict = {} - result["agents"] = from_list(lambda x: to_class(AgentInfo, x), self.agents) + result["prefix"] = from_str(self.prefix) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class AgentSelectResult: - """The newly selected custom agent.""" +class SessionsFindByPrefixResult: + """Session ID matching the prefix, omitted when no unique match exists.""" - agent: AgentInfo - """The newly selected custom agent""" + session_id: str | None = None + """Omitted when no unique session matches the prefix (no match or ambiguous)""" @staticmethod - def from_dict(obj: Any) -> 'AgentSelectResult': + def from_dict(obj: Any) -> 'SessionsFindByPrefixResult': assert isinstance(obj, dict) - agent = AgentInfo.from_dict(obj.get("agent")) - return AgentSelectResult(agent) + session_id = from_union([from_str, from_none], obj.get("sessionId")) + return SessionsFindByPrefixResult(session_id) def to_dict(self) -> dict: result: dict = {} - result["agent"] = to_class(AgentInfo, self.agent) + if self.session_id is not None: + result["sessionId"] = from_union([from_str, from_none], self.session_id) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SessionAuthStatus: - """Authentication status and account metadata for the session.""" - - is_authenticated: bool - """Whether the session has resolved authentication""" +class SessionsFindByTaskIDRequest: + """GitHub task ID to look up.""" - auth_type: AuthInfoType | None = None - """Authentication type""" + task_id: str + """GitHub task ID to look up""" - copilot_plan: str | None = None - """Copilot plan tier (e.g., individual_pro, business)""" + @staticmethod + def from_dict(obj: Any) -> 'SessionsFindByTaskIDRequest': + assert isinstance(obj, dict) + task_id = from_str(obj.get("taskId")) + return SessionsFindByTaskIDRequest(task_id) - host: str | None = None - """Authentication host URL""" + def to_dict(self) -> dict: + result: dict = {} + result["taskId"] = from_str(self.task_id) + return result - login: str | None = None - """Authenticated login/username, if available""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsFindByTaskIDResult: + """ID of the local session bound to the given GitHub task, or omitted when none.""" - status_message: str | None = None - """Human-readable authentication status description""" + session_id: str | None = None + """Omitted when no local session is bound to that GitHub task""" @staticmethod - def from_dict(obj: Any) -> 'SessionAuthStatus': + def from_dict(obj: Any) -> 'SessionsFindByTaskIDResult': assert isinstance(obj, dict) - is_authenticated = from_bool(obj.get("isAuthenticated")) - auth_type = from_union([AuthInfoType, from_none], obj.get("authType")) - copilot_plan = from_union([from_str, from_none], obj.get("copilotPlan")) - host = from_union([from_str, from_none], obj.get("host")) - login = from_union([from_str, from_none], obj.get("login")) - status_message = from_union([from_str, from_none], obj.get("statusMessage")) - return SessionAuthStatus(is_authenticated, auth_type, copilot_plan, host, login, status_message) + session_id = from_union([from_str, from_none], obj.get("sessionId")) + return SessionsFindByTaskIDResult(session_id) def to_dict(self) -> dict: result: dict = {} - result["isAuthenticated"] = from_bool(self.is_authenticated) - if self.auth_type is not None: - result["authType"] = from_union([lambda x: to_enum(AuthInfoType, x), from_none], self.auth_type) - if self.copilot_plan is not None: - result["copilotPlan"] = from_union([from_str, from_none], self.copilot_plan) - if self.host is not None: - result["host"] = from_union([from_str, from_none], self.host) - if self.login is not None: - result["login"] = from_union([from_str, from_none], self.login) - if self.status_message is not None: - result["statusMessage"] = from_union([from_str, from_none], self.status_message) + if self.session_id is not None: + result["sessionId"] = from_union([from_str, from_none], self.session_id) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SlashCommandInput: - """Optional unstructured input hint""" - - hint: str - """Hint to display when command input has not been provided""" +class SessionsForkRequest: + """Source session identifier to fork from, optional event-ID boundary, and optional friendly + name for the new session. + """ + session_id: str + """Source session ID to fork from""" - completion: SlashCommandInputCompletion | None = None - """Optional completion hint for the input (e.g. 'directory' for filesystem path completion)""" + name: str | None = None + """Optional friendly name to assign to the forked session.""" - preserve_multiline_input: bool | None = None - """When true, clients should pass the full text after the command name as a single argument - rather than splitting on whitespace - """ - required: bool | None = None - """When true, the command requires non-empty input; clients should render the input hint as - required + to_event_id: str | None = None + """Optional event ID boundary. When provided, the fork includes only events before this ID + (exclusive). When omitted, all events are included. """ @staticmethod - def from_dict(obj: Any) -> 'SlashCommandInput': + def from_dict(obj: Any) -> 'SessionsForkRequest': assert isinstance(obj, dict) - hint = from_str(obj.get("hint")) - completion = from_union([SlashCommandInputCompletion, from_none], obj.get("completion")) - preserve_multiline_input = from_union([from_bool, from_none], obj.get("preserveMultilineInput")) - required = from_union([from_bool, from_none], obj.get("required")) - return SlashCommandInput(hint, completion, preserve_multiline_input, required) + session_id = from_str(obj.get("sessionId")) + name = from_union([from_str, from_none], obj.get("name")) + to_event_id = from_union([from_str, from_none], obj.get("toEventId")) + return SessionsForkRequest(session_id, name, to_event_id) def to_dict(self) -> dict: result: dict = {} - result["hint"] = from_str(self.hint) - if self.completion is not None: - result["completion"] = from_union([lambda x: to_enum(SlashCommandInputCompletion, x), from_none], self.completion) - if self.preserve_multiline_input is not None: - result["preserveMultilineInput"] = from_union([from_bool, from_none], self.preserve_multiline_input) - if self.required is not None: - result["required"] = from_union([from_bool, from_none], self.required) + result["sessionId"] = from_str(self.session_id) + if self.name is not None: + result["name"] = from_union([from_str, from_none], self.name) + if self.to_event_id is not None: + result["toEventId"] = from_union([from_str, from_none], self.to_event_id) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ConnectedRemoteSessionMetadata: - """Metadata for a connected remote session.""" - - kind: ConnectedRemoteSessionMetadataKind - """Neutral SDK discriminator for the connected remote session kind.""" - - modified_time: datetime - """Last session update time as an ISO 8601 string.""" - - repository: ConnectedRemoteSessionMetadataRepository - """Repository associated with the connected remote session.""" +class SessionsForkResult: + """Identifier and optional friendly name assigned to the newly forked session.""" session_id: str - """SDK session ID for the connected remote session.""" - - start_time: datetime - """Session start time as an ISO 8601 string.""" + """The new forked session's ID""" name: str | None = None - """Optional friendly session name.""" + """Friendly name assigned to the forked session, if any.""" - pull_request_number: int | None = None - """Pull request number associated with the session.""" + @staticmethod + def from_dict(obj: Any) -> 'SessionsForkResult': + assert isinstance(obj, dict) + session_id = from_str(obj.get("sessionId")) + name = from_union([from_str, from_none], obj.get("name")) + return SessionsForkResult(session_id, name) - resource_id: str | None = None - """Original remote resource identifier.""" - - stale_at: datetime | None = None - """Remote session staleness deadline as an ISO 8601 string.""" + def to_dict(self) -> dict: + result: dict = {} + result["sessionId"] = from_str(self.session_id) + if self.name is not None: + result["name"] = from_union([from_str, from_none], self.name) + return result - state: str | None = None - """Remote session state returned by the backing service.""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsGetEventFilePathRequest: + """Session ID whose event-log file path to compute.""" - summary: str | None = None - """Optional session summary.""" + session_id: str + """Session ID whose event-log file path to compute""" @staticmethod - def from_dict(obj: Any) -> 'ConnectedRemoteSessionMetadata': + def from_dict(obj: Any) -> 'SessionsGetEventFilePathRequest': assert isinstance(obj, dict) - kind = ConnectedRemoteSessionMetadataKind(obj.get("kind")) - modified_time = from_datetime(obj.get("modifiedTime")) - repository = ConnectedRemoteSessionMetadataRepository.from_dict(obj.get("repository")) session_id = from_str(obj.get("sessionId")) - start_time = from_datetime(obj.get("startTime")) - name = from_union([from_str, from_none], obj.get("name")) - pull_request_number = from_union([from_int, from_none], obj.get("pullRequestNumber")) - resource_id = from_union([from_str, from_none], obj.get("resourceId")) - stale_at = from_union([from_datetime, from_none], obj.get("staleAt")) - state = from_union([from_str, from_none], obj.get("state")) - summary = from_union([from_str, from_none], obj.get("summary")) - return ConnectedRemoteSessionMetadata(kind, modified_time, repository, session_id, start_time, name, pull_request_number, resource_id, stale_at, state, summary) + return SessionsGetEventFilePathRequest(session_id) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(ConnectedRemoteSessionMetadataKind, self.kind) - result["modifiedTime"] = self.modified_time.isoformat() - result["repository"] = to_class(ConnectedRemoteSessionMetadataRepository, self.repository) result["sessionId"] = from_str(self.session_id) - result["startTime"] = self.start_time.isoformat() - if self.name is not None: - result["name"] = from_union([from_str, from_none], self.name) - if self.pull_request_number is not None: - result["pullRequestNumber"] = from_union([from_int, from_none], self.pull_request_number) - if self.resource_id is not None: - result["resourceId"] = from_union([from_str, from_none], self.resource_id) - if self.stale_at is not None: - result["staleAt"] = from_union([lambda x: x.isoformat(), from_none], self.stale_at) - if self.state is not None: - result["state"] = from_union([from_str, from_none], self.state) - if self.summary is not None: - result["summary"] = from_union([from_str, from_none], self.summary) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class MCPServerConfigStdio: - """Stdio MCP server configuration launched as a child process.""" - - command: str - """Executable command used to start the Stdio MCP server process.""" - - args: list[str] | None = None - """Command-line arguments passed to the Stdio MCP server process.""" - - cwd: str | None = None - """Working directory for the Stdio MCP server process.""" - - env: dict[str, str] | None = None - """Environment variables to pass to the Stdio MCP server process.""" - - filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None - """Content filtering mode to apply to all tools, or a map of tool name to content filtering - mode. - """ - is_default_server: bool | None = None - """Whether this server is a built-in fallback used when the user has not configured their - own server. - """ - timeout: int | None = None - """Timeout in milliseconds for tool calls to this server.""" +class SessionsGetEventFilePathResult: + """Absolute path to the session's events.jsonl file on disk.""" - tools: list[str] | None = None - """Tools to include. Defaults to all tools if not specified.""" + file_path: str + """Absolute path to the session's events.jsonl file""" @staticmethod - def from_dict(obj: Any) -> 'MCPServerConfigStdio': + def from_dict(obj: Any) -> 'SessionsGetEventFilePathResult': assert isinstance(obj, dict) - command = from_str(obj.get("command")) - args = from_union([lambda x: from_list(from_str, x), from_none], obj.get("args")) - 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(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) - is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - timeout = from_union([from_int, from_none], obj.get("timeout")) - tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - return MCPServerConfigStdio(command, args, cwd, env, filter_mapping, is_default_server, timeout, tools) + file_path = from_str(obj.get("filePath")) + return SessionsGetEventFilePathResult(file_path) def to_dict(self) -> dict: result: dict = {} - result["command"] = from_str(self.command) - if self.args is not None: - result["args"] = from_union([lambda x: from_list(from_str, x), from_none], self.args) - if self.cwd is not None: - result["cwd"] = from_union([from_str, from_none], self.cwd) - 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(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) - if self.is_default_server is not None: - result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) - if self.timeout is not None: - result["timeout"] = from_union([from_int, from_none], self.timeout) - if self.tools is not None: - result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) + result["filePath"] = from_str(self.file_path) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class DiscoveredMCPServer: - """Schema for the `DiscoveredMcpServer` type.""" - - enabled: bool - """Whether the server is enabled (not in the disabled list)""" +class SessionsGetLastForContextResult: + """Most-relevant session ID for the supplied context, or omitted when no sessions exist.""" - name: str - """Server name (config key)""" - - source: McpServerSource - """Configuration source: user, workspace, plugin, or builtin""" - - type: DiscoveredMCPServerType | None = None - """Server transport type: stdio, http, sse, or memory""" + session_id: str | None = None + """Most-relevant session ID for the supplied context, or omitted when no sessions exist""" @staticmethod - def from_dict(obj: Any) -> 'DiscoveredMCPServer': + def from_dict(obj: Any) -> 'SessionsGetLastForContextResult': assert isinstance(obj, dict) - enabled = from_bool(obj.get("enabled")) - name = from_str(obj.get("name")) - source = McpServerSource(obj.get("source")) - type = from_union([DiscoveredMCPServerType, from_none], obj.get("type")) - return DiscoveredMCPServer(enabled, name, source, type) + session_id = from_union([from_str, from_none], obj.get("sessionId")) + return SessionsGetLastForContextResult(session_id) def to_dict(self) -> dict: result: dict = {} - result["enabled"] = from_bool(self.enabled) - result["name"] = from_str(self.name) - result["source"] = to_enum(McpServerSource, self.source) - if self.type is not None: - result["type"] = from_union([lambda x: to_enum(DiscoveredMCPServerType, x), from_none], self.type) + if self.session_id is not None: + result["sessionId"] = from_union([from_str, from_none], self.session_id) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class Extension: - """Schema for the `Extension` type.""" - - id: str - """Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper')""" +class SessionsGetPersistedRemoteSteerableRequest: + """Session ID to look up the persisted remote-steerable flag for.""" - name: str - """Extension name (directory name)""" - - source: ExtensionSource - """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" - - status: ExtensionStatus - """Current status: running, disabled, failed, or starting""" - - pid: int | None = None - """Process ID if the extension is running""" + session_id: str + """Session ID to look up the persisted remote-steerable flag for""" @staticmethod - def from_dict(obj: Any) -> 'Extension': + def from_dict(obj: Any) -> 'SessionsGetPersistedRemoteSteerableRequest': assert isinstance(obj, dict) - id = from_str(obj.get("id")) - name = from_str(obj.get("name")) - 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) + session_id = from_str(obj.get("sessionId")) + return SessionsGetPersistedRemoteSteerableRequest(session_id) def to_dict(self) -> dict: result: dict = {} - result["id"] = from_str(self.id) - result["name"] = from_str(self.name) - 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) + 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 ExternalToolTextResultForLlmBinaryResultsForLlm: - """Binary result returned by a tool for the model""" - - data: str - """Base64-encoded binary data""" - - mime_type: str - """MIME type of the binary data""" - - type: ExternalToolTextResultForLlmBinaryResultsForLlmType - """Binary result type discriminator. Use "image" for images and "resource" for other binary - data. +class SessionsGetPersistedRemoteSteerableResult: + """The session's persisted remote-steerable flag, or omitted when no value has been + persisted. + """ + remote_steerable: bool | None = None + """The session's persisted remote-steerable flag if recorded; omitted when no value has been + persisted """ - description: str | None = None - """Human-readable description of the binary data""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmBinaryResultsForLlm': + def from_dict(obj: Any) -> 'SessionsGetPersistedRemoteSteerableResult': assert isinstance(obj, dict) - data = from_str(obj.get("data")) - mime_type = from_str(obj.get("mimeType")) - type = ExternalToolTextResultForLlmBinaryResultsForLlmType(obj.get("type")) - description = from_union([from_str, from_none], obj.get("description")) - return ExternalToolTextResultForLlmBinaryResultsForLlm(data, mime_type, type, description) + remote_steerable = from_union([from_bool, from_none], obj.get("remoteSteerable")) + return SessionsGetPersistedRemoteSteerableResult(remote_steerable) def to_dict(self) -> dict: result: dict = {} - result["data"] = from_str(self.data) - result["mimeType"] = from_str(self.mime_type) - result["type"] = to_enum(ExternalToolTextResultForLlmBinaryResultsForLlmType, self.type) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) + if self.remote_steerable is not None: + result["remoteSteerable"] = from_union([from_bool, from_none], self.remote_steerable) return result @dataclass -class ExternalToolTextResultForLlmContentResourceLinkIcon: - """Icon image for a resource""" +class Filter: + """Optional filter applied to the returned sessions""" - src: str - """URL or path to the icon image""" + branch: str | None = None + """Match sessions whose context.branch equals this value""" - mime_type: str | None = None - """MIME type of the icon image""" + cwd: str | None = None + """Match sessions whose context.cwd equals this value""" - sizes: list[str] | None = None - """Available icon sizes (e.g., ['16x16', '32x32'])""" + git_root: str | None = None + """Match sessions whose context.gitRoot equals this value""" - theme: ExternalToolTextResultForLlmContentResourceLinkIconTheme | None = None - """Theme variant this icon is intended for""" + repository: str | None = None + """Match sessions whose context.repository equals this value""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentResourceLinkIcon': + def from_dict(obj: Any) -> 'Filter': 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([ExternalToolTextResultForLlmContentResourceLinkIconTheme, from_none], obj.get("theme")) - return ExternalToolTextResultForLlmContentResourceLinkIcon(src, mime_type, sizes, theme) + branch = from_union([from_str, from_none], obj.get("branch")) + cwd = from_union([from_str, from_none], obj.get("cwd")) + git_root = from_union([from_str, from_none], obj.get("gitRoot")) + repository = from_union([from_str, from_none], obj.get("repository")) + return Filter(branch, cwd, git_root, repository) def to_dict(self) -> dict: result: dict = {} - result["src"] = from_str(self.src) - if self.mime_type is not None: - result["mimeType"] = from_union([from_str, from_none], self.mime_type) - 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(ExternalToolTextResultForLlmContentResourceLinkIconTheme, x), from_none], self.theme) + if self.branch is not None: + result["branch"] = from_union([from_str, from_none], self.branch) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + if self.git_root is not None: + result["gitRoot"] = from_union([from_str, from_none], self.git_root) + if self.repository is not None: + result["repository"] = from_union([from_str, from_none], self.repository) return result -ExternalToolTextResultForLlmContentResourceDetails = EmbeddedTextResourceContents | EmbeddedBlobResourceContents - +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ExternalToolTextResultForLlmContentAudio: - """Audio content block with base64-encoded data""" - - data: str - """Base64-encoded audio data""" - - mime_type: str - """MIME type of the audio (e.g., audio/wav, audio/mpeg)""" +class SessionsLoadDeferredRepoHooksRequest: + """Active session ID whose deferred repo-level hooks should be loaded.""" - type: ExternalToolTextResultForLlmContentAudioType - """Content block type discriminator""" + session_id: str + """Active session ID whose deferred repo-level hooks should be loaded""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentAudio': + def from_dict(obj: Any) -> 'SessionsLoadDeferredRepoHooksRequest': assert isinstance(obj, dict) - data = from_str(obj.get("data")) - mime_type = from_str(obj.get("mimeType")) - type = ExternalToolTextResultForLlmContentAudioType(obj.get("type")) - return ExternalToolTextResultForLlmContentAudio(data, mime_type, type) + session_id = from_str(obj.get("sessionId")) + return SessionsLoadDeferredRepoHooksRequest(session_id) def to_dict(self) -> dict: result: dict = {} - result["data"] = from_str(self.data) - result["mimeType"] = from_str(self.mime_type) - result["type"] = to_enum(ExternalToolTextResultForLlmContentAudioType, self.type) + 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 ExternalToolTextResultForLlmContentImage: - """Image content block with base64-encoded data""" +class SessionsPruneOldRequest: + """Age threshold and optional flags controlling which old sessions are pruned (or simulated + when dryRun is true). + """ + older_than_days: int + """Delete sessions whose modifiedTime is at least this many days old""" - data: str - """Base64-encoded image data""" + dry_run: bool | None = None + """When true, only report what would be deleted without performing any deletion""" - mime_type: str - """MIME type of the image (e.g., image/png, image/jpeg)""" + exclude_session_ids: list[str] | None = None + """Session IDs that should never be considered for pruning""" - type: ExternalToolTextResultForLlmContentImageType - """Content block type discriminator""" + include_named: bool | None = None + """When true, named sessions (set via /rename) are also eligible for pruning""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentImage': + def from_dict(obj: Any) -> 'SessionsPruneOldRequest': assert isinstance(obj, dict) - data = from_str(obj.get("data")) - mime_type = from_str(obj.get("mimeType")) - type = ExternalToolTextResultForLlmContentImageType(obj.get("type")) - return ExternalToolTextResultForLlmContentImage(data, mime_type, type) + older_than_days = from_int(obj.get("olderThanDays")) + dry_run = from_union([from_bool, from_none], obj.get("dryRun")) + exclude_session_ids = from_union([lambda x: from_list(from_str, x), from_none], obj.get("excludeSessionIds")) + include_named = from_union([from_bool, from_none], obj.get("includeNamed")) + return SessionsPruneOldRequest(older_than_days, dry_run, exclude_session_ids, include_named) def to_dict(self) -> dict: result: dict = {} - result["data"] = from_str(self.data) - result["mimeType"] = from_str(self.mime_type) - result["type"] = to_enum(ExternalToolTextResultForLlmContentImageType, self.type) + result["olderThanDays"] = from_int(self.older_than_days) + if self.dry_run is not None: + result["dryRun"] = from_union([from_bool, from_none], self.dry_run) + if self.exclude_session_ids is not None: + result["excludeSessionIds"] = from_union([lambda x: from_list(from_str, x), from_none], self.exclude_session_ids) + if self.include_named is not None: + result["includeNamed"] = from_union([from_bool, from_none], self.include_named) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ExternalToolTextResultForLlmContentResource: - """Embedded resource content block with inline text or binary data""" - - resource: ExternalToolTextResultForLlmContentResourceDetails - """The embedded resource contents, either text or base64-encoded binary""" +class SessionsReleaseLockRequest: + """Session ID whose in-use lock should be released.""" - type: ExternalToolTextResultForLlmContentResourceType - """Content block type discriminator""" + session_id: str + """Session ID whose in-use lock should be released""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentResource': + def from_dict(obj: Any) -> 'SessionsReleaseLockRequest': assert isinstance(obj, dict) - resource = (lambda x: from_union([EmbeddedTextResourceContents.from_dict, EmbeddedBlobResourceContents.from_dict], x))(obj.get("resource")) - type = ExternalToolTextResultForLlmContentResourceType(obj.get("type")) - return ExternalToolTextResultForLlmContentResource(resource, type) + session_id = from_str(obj.get("sessionId")) + return SessionsReleaseLockRequest(session_id) def to_dict(self) -> dict: result: dict = {} - result["resource"] = from_union([lambda x: to_class(EmbeddedTextResourceContents, x), lambda x: to_class(EmbeddedBlobResourceContents, x)], self.resource) - result["type"] = to_enum(ExternalToolTextResultForLlmContentResourceType, self.type) + 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 ExternalToolTextResultForLlmContentTerminal: - """Terminal/shell output content block with optional exit code and working directory""" +class SessionsReleaseLockResult: + """Release the in-use lock held by this process for the given session. No-op when this + process does not currently hold a lock for the session. + """ + @staticmethod + def from_dict(obj: Any) -> 'SessionsReleaseLockResult': + assert isinstance(obj, dict) + return SessionsReleaseLockResult() - text: str - """Terminal/shell output text""" + def to_dict(self) -> dict: + result: dict = {} + return result - type: ExternalToolTextResultForLlmContentTerminalType - """Content block type discriminator""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsReloadPluginHooksRequest: + """Active session ID and an optional flag for deferring repo-level hooks until folder trust.""" - cwd: str | None = None - """Working directory where the command was executed""" + session_id: str + """Active session ID to reload hooks for""" - exit_code: float | None = None - """Process exit code, if the command has completed""" + defer_repo_hooks: bool | None = None + """When true, skip repo-level hooks. Use before folder trust is confirmed; + loadDeferredRepoHooks loads them post-trust. + """ @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentTerminal': + def from_dict(obj: Any) -> 'SessionsReloadPluginHooksRequest': assert isinstance(obj, dict) - text = from_str(obj.get("text")) - type = ExternalToolTextResultForLlmContentTerminalType(obj.get("type")) - cwd = from_union([from_str, from_none], obj.get("cwd")) - exit_code = from_union([from_float, from_none], obj.get("exitCode")) - return ExternalToolTextResultForLlmContentTerminal(text, type, cwd, exit_code) + session_id = from_str(obj.get("sessionId")) + defer_repo_hooks = from_union([from_bool, from_none], obj.get("deferRepoHooks")) + return SessionsReloadPluginHooksRequest(session_id, defer_repo_hooks) def to_dict(self) -> dict: result: dict = {} - result["text"] = from_str(self.text) - result["type"] = to_enum(ExternalToolTextResultForLlmContentTerminalType, self.type) - if self.cwd is not None: - result["cwd"] = from_union([from_str, from_none], self.cwd) - if self.exit_code is not None: - result["exitCode"] = from_union([to_float, from_none], self.exit_code) + result["sessionId"] = from_str(self.session_id) + if self.defer_repo_hooks is not None: + result["deferRepoHooks"] = from_union([from_bool, from_none], self.defer_repo_hooks) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ExternalToolTextResultForLlmContentText: - """Plain text content block""" - - text: str - """The text content""" - - type: KindEnum - """Content block type discriminator""" - +class SessionsReloadPluginHooksResult: + """Reload all hooks (user, plugin, optionally repo) and apply them to the active session. + Call after installing or removing plugins so their hooks take effect immediately. No-op + when no active session matches the given sessionId. + """ @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentText': + def from_dict(obj: Any) -> 'SessionsReloadPluginHooksResult': assert isinstance(obj, dict) - text = from_str(obj.get("text")) - type = KindEnum(obj.get("type")) - return ExternalToolTextResultForLlmContentText(text, type) + return SessionsReloadPluginHooksResult() def to_dict(self) -> dict: result: dict = {} - result["text"] = from_str(self.text) - result["type"] = to_enum(KindEnum, self.type) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SlashCommandTextResult: - """Schema for the `SlashCommandTextResult` type.""" +class SessionsSaveRequest: + """Session ID whose pending events should be flushed to disk.""" - kind: KindEnum - """Text result discriminator""" - - text: str - """Text output for the client to render""" + session_id: str + """Session ID whose pending events should be flushed to disk""" - markdown: bool | None = None - """Whether text contains Markdown""" + @staticmethod + def from_dict(obj: Any) -> 'SessionsSaveRequest': + assert isinstance(obj, dict) + session_id = from_str(obj.get("sessionId")) + return SessionsSaveRequest(session_id) - preserve_ansi: bool | None = None - """Whether ANSI sequences should be preserved""" + def to_dict(self) -> dict: + result: dict = {} + result["sessionId"] = from_str(self.session_id) + return result - runtime_settings_changed: bool | None = None - """True when the invocation mutated user runtime settings; consumers caching settings should - refresh +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsSaveResult: + """Flush a session's pending events to disk. No-op when no writer exists for the session + (e.g., already closed). """ - @staticmethod - def from_dict(obj: Any) -> 'SlashCommandTextResult': + def from_dict(obj: Any) -> 'SessionsSaveResult': assert isinstance(obj, dict) - kind = KindEnum(obj.get("kind")) - text = from_str(obj.get("text")) - markdown = from_union([from_bool, from_none], obj.get("markdown")) - preserve_ansi = from_union([from_bool, from_none], obj.get("preserveAnsi")) - runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) - return SlashCommandTextResult(kind, text, markdown, preserve_ansi, runtime_settings_changed) + return SessionsSaveResult() def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(KindEnum, self.kind) - result["text"] = from_str(self.text) - if self.markdown is not None: - result["markdown"] = from_union([from_bool, from_none], self.markdown) - if self.preserve_ansi is not None: - result["preserveAnsi"] = from_union([from_bool, from_none], self.preserve_ansi) - if self.runtime_settings_changed is not None: - result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class HistoryCompactResult: - """Compaction outcome with the number of tokens and messages removed and the resulting - context window breakdown. +class SessionsSetAdditionalPluginsResult: + """Replace the manager-wide additional plugins. New session creations and subsequent hook + reloads see the new set; already-running sessions keep their existing hook installation + until the next reload. """ - messages_removed: int - """Number of messages removed during compaction""" - - success: bool - """Whether compaction completed successfully""" - - tokens_removed: int - """Number of tokens freed by compaction""" - - context_window: HistoryCompactContextWindow | None = None - """Post-compaction context window usage breakdown""" - @staticmethod - def from_dict(obj: Any) -> 'HistoryCompactResult': + def from_dict(obj: Any) -> 'SessionsSetAdditionalPluginsResult': assert isinstance(obj, dict) - messages_removed = from_int(obj.get("messagesRemoved")) - success = from_bool(obj.get("success")) - tokens_removed = from_int(obj.get("tokensRemoved")) - context_window = from_union([HistoryCompactContextWindow.from_dict, from_none], obj.get("contextWindow")) - return HistoryCompactResult(messages_removed, success, tokens_removed, context_window) + return SessionsSetAdditionalPluginsResult() def to_dict(self) -> dict: result: dict = {} - result["messagesRemoved"] = from_int(self.messages_removed) - result["success"] = from_bool(self.success) - result["tokensRemoved"] = from_int(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 @dataclass -class InstructionsSources: - """Schema for the `InstructionsSources` type.""" - - content: str - """Raw content of the instruction file""" - - id: str - """Unique identifier for this source (used for toggling)""" +class ShellExecRequest: + """Shell command to run, with optional working directory and timeout in milliseconds.""" - label: str - """Human-readable label""" + command: str + """Shell command to execute""" - location: InstructionsSourcesLocation - """Where this source lives — used for UI grouping""" + cwd: str | None = None + """Working directory (defaults to session working directory)""" - source_path: str - """File path relative to repo or absolute for home""" + timeout: int | None = None + """Timeout in milliseconds (default: 30000)""" - type: InstructionsSourcesType - """Category of instruction source — used for merge logic""" + @staticmethod + 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_int, from_none], obj.get("timeout")) + return ShellExecRequest(command, cwd, timeout) - apply_to: str | None = None - """Glob pattern from frontmatter — when set, this instruction applies only to matching files""" + def to_dict(self) -> dict: + result: dict = {} + result["command"] = from_str(self.command) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + if self.timeout is not None: + result["timeout"] = from_union([from_int, from_none], self.timeout) + return result - description: str | None = None - """Short description (body after frontmatter) for use in instruction tables""" +@dataclass +class ShellExecResult: + """Identifier of the spawned process, used to correlate streamed output and exit + notifications. + """ + process_id: str + """Unique identifier for tracking streamed output""" @staticmethod - def from_dict(obj: Any) -> 'InstructionsSources': + def from_dict(obj: Any) -> 'ShellExecResult': assert isinstance(obj, dict) - content = from_str(obj.get("content")) - id = from_str(obj.get("id")) - label = from_str(obj.get("label")) - location = InstructionsSourcesLocation(obj.get("location")) - source_path = from_str(obj.get("sourcePath")) - type = InstructionsSourcesType(obj.get("type")) - apply_to = from_union([from_str, from_none], obj.get("applyTo")) - description = from_union([from_str, from_none], obj.get("description")) - return InstructionsSources(content, id, label, location, source_path, type, apply_to, description) + process_id = from_str(obj.get("processId")) + return ShellExecResult(process_id) def to_dict(self) -> dict: result: dict = {} - result["content"] = from_str(self.content) - result["id"] = from_str(self.id) - result["label"] = from_str(self.label) - result["location"] = to_enum(InstructionsSourcesLocation, self.location) - result["sourcePath"] = from_str(self.source_path) - result["type"] = to_enum(InstructionsSourcesType, self.type) - if self.apply_to is not None: - result["applyTo"] = from_union([from_str, from_none], self.apply_to) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) + result["processId"] = from_str(self.process_id) return result -@dataclass -class LogRequest: - """Message text, optional severity level, persistence flag, and optional follow-up URL.""" - - message: str - """Human-readable message""" +class ShellKillSignal(Enum): + """Signal to send (default: SIGTERM)""" - ephemeral: bool | None = None - """When true, the message is transient and not persisted to the session event log on disk""" + SIGINT = "SIGINT" + SIGKILL = "SIGKILL" + SIGTERM = "SIGTERM" - level: SessionLogLevel | None = None - """Log severity level. Determines how the message is displayed in the timeline. Defaults to - "info". +@dataclass +class ShellKillResult: + """Indicates whether the signal was delivered; false if the process was unknown or already + exited. """ - url: str | None = None - """Optional URL the user can open in their browser for more details""" + killed: bool + """Whether the signal was sent successfully""" @staticmethod - def from_dict(obj: Any) -> 'LogRequest': + def from_dict(obj: Any) -> 'ShellKillResult': assert isinstance(obj, dict) - message = from_str(obj.get("message")) - ephemeral = from_union([from_bool, from_none], obj.get("ephemeral")) - level = from_union([SessionLogLevel, from_none], obj.get("level")) - url = from_union([from_str, from_none], obj.get("url")) - return LogRequest(message, ephemeral, level, url) + killed = from_bool(obj.get("killed")) + return ShellKillResult(killed) def to_dict(self) -> dict: result: dict = {} - result["message"] = from_str(self.message) - 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(SessionLogLevel, x), from_none], self.level) - if self.url is not None: - result["url"] = from_union([from_str, from_none], self.url) + result["killed"] = from_bool(self.killed) return result @dataclass -class MCPServerConfig: - """MCP server configuration (stdio process or remote HTTP/SSE) - - Stdio MCP server configuration launched as a child process. +class ShutdownRequest: + """Parameters for shutting down the session""" - Remote MCP server configuration accessed over HTTP or SSE. + reason: str | None = None + """Optional human-readable reason. Typically the message of the error that triggered + shutdown when type is 'error'. """ - args: list[str] | None = None - """Command-line arguments passed to the Stdio MCP server process.""" + type: ShutdownType | None = None + """Why the session is being shut down. Defaults to "routine" when omitted.""" - command: str | None = None - """Executable command used to start the Stdio MCP server process.""" + @staticmethod + def from_dict(obj: Any) -> 'ShutdownRequest': + assert isinstance(obj, dict) + reason = from_union([from_str, from_none], obj.get("reason")) + type = from_union([ShutdownType, from_none], obj.get("type")) + return ShutdownRequest(reason, type) + def to_dict(self) -> dict: + result: dict = {} + if self.reason is not None: + result["reason"] = from_union([from_str, from_none], self.reason) + if self.type is not None: + result["type"] = from_union([lambda x: to_enum(ShutdownType, x), from_none], self.type) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class Skill: + """Schema for the `Skill` type.""" + + description: str + """Description of what the skill does""" + + enabled: bool + """Whether the skill is currently enabled""" + + name: str + """Unique identifier for the skill""" + + source: SkillSource + """Source location type (e.g., project, personal-copilot, plugin, builtin)""" + + user_invocable: bool + """Whether the skill can be invoked by the user as a slash command""" + + path: str | None = None + """Absolute path to the skill file""" + + plugin_name: str | None = None + """Name of the plugin that provides the skill, when source is 'plugin'""" + + @staticmethod + def from_dict(obj: Any) -> 'Skill': + assert isinstance(obj, dict) + description = from_str(obj.get("description")) + enabled = from_bool(obj.get("enabled")) + name = from_str(obj.get("name")) + source = SkillSource(obj.get("source")) + user_invocable = from_bool(obj.get("userInvocable")) + path = from_union([from_str, from_none], obj.get("path")) + plugin_name = from_union([from_str, from_none], obj.get("pluginName")) + return Skill(description, enabled, name, source, user_invocable, path, plugin_name) + + def to_dict(self) -> dict: + result: dict = {} + result["description"] = from_str(self.description) + result["enabled"] = from_bool(self.enabled) + result["name"] = from_str(self.name) + result["source"] = to_enum(SkillSource, self.source) + result["userInvocable"] = from_bool(self.user_invocable) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.plugin_name is not None: + result["pluginName"] = from_union([from_str, from_none], self.plugin_name) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SkillsDisableRequest: + """Name of the skill to disable for the session.""" + + name: str + """Name of the skill to disable""" + + @staticmethod + def from_dict(obj: Any) -> 'SkillsDisableRequest': + assert isinstance(obj, dict) + name = from_str(obj.get("name")) + return SkillsDisableRequest(name) + + def to_dict(self) -> dict: + result: dict = {} + result["name"] = from_str(self.name) + return result + +@dataclass +class SkillsDiscoverRequest: + """Optional project paths and additional skill directories to include in discovery.""" + + project_paths: list[str] | None = None + """Optional list of project directory paths to scan for project-scoped skills""" + + skill_directories: list[str] | None = None + """Optional list of additional skill directory paths to include""" + + @staticmethod + def from_dict(obj: Any) -> 'SkillsDiscoverRequest': + assert isinstance(obj, dict) + project_paths = from_union([lambda x: from_list(from_str, x), from_none], obj.get("projectPaths")) + skill_directories = from_union([lambda x: from_list(from_str, x), from_none], obj.get("skillDirectories")) + return SkillsDiscoverRequest(project_paths, skill_directories) + + def to_dict(self) -> dict: + result: dict = {} + if self.project_paths is not None: + result["projectPaths"] = from_union([lambda x: from_list(from_str, x), from_none], self.project_paths) + if self.skill_directories is not None: + result["skillDirectories"] = from_union([lambda x: from_list(from_str, x), from_none], self.skill_directories) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SkillsEnableRequest: + """Name of the skill to enable for the session.""" + + name: str + """Name of the skill to enable""" + + @staticmethod + def from_dict(obj: Any) -> 'SkillsEnableRequest': + assert isinstance(obj, dict) + name = from_str(obj.get("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 SkillsInvokedSkill: + """Schema for the `SkillsInvokedSkill` type.""" + + content: str + """Full content of the skill file""" + + invoked_at_turn: int + """Turn number when the skill was invoked""" + + name: str + """Unique identifier for the skill""" + + path: str + """Path to the SKILL.md file""" + + allowed_tools: list[str] | None = None + """Tools that should be auto-approved when this skill is active, captured at invocation time""" + + @staticmethod + def from_dict(obj: Any) -> 'SkillsInvokedSkill': + assert isinstance(obj, dict) + content = from_str(obj.get("content")) + invoked_at_turn = from_int(obj.get("invokedAtTurn")) + name = from_str(obj.get("name")) + path = from_str(obj.get("path")) + allowed_tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("allowedTools")) + return SkillsInvokedSkill(content, invoked_at_turn, name, path, allowed_tools) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_str(self.content) + result["invokedAtTurn"] = from_int(self.invoked_at_turn) + result["name"] = from_str(self.name) + result["path"] = from_str(self.path) + if self.allowed_tools is not None: + result["allowedTools"] = from_union([lambda x: from_list(from_str, x), from_none], self.allowed_tools) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SkillsLoadDiagnostics: + """Diagnostics from reloading skill definitions, with warnings and errors as separate lists.""" + + errors: list[str] + """Errors emitted while loading skills (e.g. skills that failed to load entirely)""" + + warnings: list[str] + """Warnings emitted while loading skills (e.g. skills that loaded but had issues)""" + + @staticmethod + def from_dict(obj: Any) -> 'SkillsLoadDiagnostics': + assert isinstance(obj, dict) + errors = from_list(from_str, obj.get("errors")) + warnings = from_list(from_str, obj.get("warnings")) + return SkillsLoadDiagnostics(errors, warnings) + + def to_dict(self) -> dict: + result: dict = {} + result["errors"] = from_list(from_str, self.errors) + result["warnings"] = from_list(from_str, self.warnings) + return result + +class SlashCommandAgentPromptResultKind(Enum): + AGENT_PROMPT = "agent-prompt" + +class SlashCommandCompletedResultKind(Enum): + COMPLETED = "completed" + +class SlashCommandInvocationResultKind(Enum): + AGENT_PROMPT = "agent-prompt" + COMPLETED = "completed" + TEXT = "text" + +# Experimental: this type is part of an experimental API and may change or be removed. +class TaskExecutionMode(Enum): + """Whether task execution is synchronously awaited or managed in the background""" + + BACKGROUND = "background" + SYNC = "sync" + +# Experimental: this type is part of an experimental API and may change or be removed. +class TaskStatus(Enum): + """Current lifecycle status of the task""" + + CANCELLED = "cancelled" + COMPLETED = "completed" + FAILED = "failed" + IDLE = "idle" + RUNNING = "running" + +class TaskAgentInfoType(Enum): + AGENT = "agent" + +@dataclass +class RecentActivity: + message: str + """Display message, e.g., "▸ bash", "✓ edit src/foo.ts\"""" + + timestamp: datetime + """ISO 8601 timestamp when this event occurred""" + + @staticmethod + def from_dict(obj: Any) -> 'RecentActivity': + assert isinstance(obj, dict) + message = from_str(obj.get("message")) + timestamp = from_datetime(obj.get("timestamp")) + return RecentActivity(message, timestamp) + + def to_dict(self) -> dict: + result: dict = {} + result["message"] = from_str(self.message) + result["timestamp"] = self.timestamp.isoformat() + return result + +class TaskAgentProgressType(Enum): + AGENT = "agent" + SHELL = "shell" + +# Experimental: this type is part of an experimental API and may change or be removed. +class TaskShellInfoAttachmentMode(Enum): + """Whether the shell runs inside a managed PTY session or as an independent background + process + """ + ATTACHED = "attached" + DETACHED = "detached" + +class TaskShellInfoType(Enum): + SHELL = "shell" + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksCancelRequest: + """Identifier of the background task to cancel.""" + + id: str + """Task identifier""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksCancelRequest': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + return TasksCancelRequest(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 TasksCancelResult: + """Indicates whether the background task was successfully cancelled.""" + + cancelled: bool + """Whether the task was successfully cancelled""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksCancelResult': + assert isinstance(obj, dict) + cancelled = from_bool(obj.get("cancelled")) + return TasksCancelResult(cancelled) + + def to_dict(self) -> dict: + result: dict = {} + result["cancelled"] = from_bool(self.cancelled) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksGetProgressRequest: + """Identifier of the background task to fetch progress for.""" + + id: str + """Task identifier (agent ID or shell ID)""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksGetProgressRequest': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + return TasksGetProgressRequest(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 TasksPromoteToBackgroundRequest: + """Identifier of the task to promote to background mode.""" + + id: str + """Task identifier""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksPromoteToBackgroundRequest': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + return TasksPromoteToBackgroundRequest(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 TasksPromoteToBackgroundResult: + """Indicates whether the task was successfully promoted to background mode.""" + + promoted: bool + """Whether the task was successfully promoted to background mode""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksPromoteToBackgroundResult': + assert isinstance(obj, dict) + promoted = from_bool(obj.get("promoted")) + return TasksPromoteToBackgroundResult(promoted) + + def to_dict(self) -> dict: + result: dict = {} + result["promoted"] = from_bool(self.promoted) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksRefreshResult: + """Refresh metadata for any detached background shells the runtime knows about. Use after a + long pause to pick up exit/output state for shells running outside the agent loop. + """ + @staticmethod + def from_dict(obj: Any) -> 'TasksRefreshResult': + assert isinstance(obj, dict) + return TasksRefreshResult() + + 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 TasksRemoveRequest: + """Identifier of the completed or cancelled task to remove from tracking.""" + + id: str + """Task identifier""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksRemoveRequest': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + return TasksRemoveRequest(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 TasksRemoveResult: + """Indicates whether the task was removed. False when the task does not exist or is still + running/idle. + """ + removed: bool + """Whether the task was removed. Returns false if the task does not exist or is still + running/idle (cancel it first). + """ + + @staticmethod + def from_dict(obj: Any) -> 'TasksRemoveResult': + assert isinstance(obj, dict) + removed = from_bool(obj.get("removed")) + return TasksRemoveResult(removed) + + def to_dict(self) -> dict: + result: dict = {} + result["removed"] = from_bool(self.removed) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksSendMessageRequest: + """Identifier of the target agent task, message content, and optional sender agent ID.""" + + id: str + """Agent task identifier""" + + message: str + """Message content to send to the agent""" + + from_agent_id: str | None = None + """Agent ID of the sender, if sent on behalf of another agent""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksSendMessageRequest': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + message = from_str(obj.get("message")) + from_agent_id = from_union([from_str, from_none], obj.get("fromAgentId")) + return TasksSendMessageRequest(id, message, from_agent_id) + + def to_dict(self) -> dict: + result: dict = {} + result["id"] = from_str(self.id) + result["message"] = from_str(self.message) + if self.from_agent_id is not None: + result["fromAgentId"] = from_union([from_str, from_none], self.from_agent_id) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksSendMessageResult: + """Indicates whether the message was delivered, with an error message when delivery failed.""" + + sent: bool + """Whether the message was successfully delivered or steered""" + + error: str | None = None + """Error message if delivery failed""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksSendMessageResult': + assert isinstance(obj, dict) + sent = from_bool(obj.get("sent")) + error = from_union([from_str, from_none], obj.get("error")) + return TasksSendMessageResult(sent, error) + + def to_dict(self) -> dict: + result: dict = {} + result["sent"] = from_bool(self.sent) + if self.error is not None: + result["error"] = from_union([from_str, from_none], self.error) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksStartAgentRequest: + """Agent type, prompt, name, and optional description and model override for the new task.""" + + agent_type: str + """Type of agent to start (e.g., 'explore', 'task', 'general-purpose')""" + + name: str + """Short name for the agent, used to generate a human-readable ID""" + + prompt: str + """Task prompt for the agent""" + + description: str | None = None + """Short description of the task""" + + model: str | None = None + """Optional model override""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksStartAgentRequest': + assert isinstance(obj, dict) + agent_type = from_str(obj.get("agentType")) + name = from_str(obj.get("name")) + prompt = from_str(obj.get("prompt")) + description = from_union([from_str, from_none], obj.get("description")) + model = from_union([from_str, from_none], obj.get("model")) + return TasksStartAgentRequest(agent_type, name, prompt, description, model) + + def to_dict(self) -> dict: + result: dict = {} + result["agentType"] = from_str(self.agent_type) + result["name"] = from_str(self.name) + result["prompt"] = from_str(self.prompt) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksStartAgentResult: + """Identifier assigned to the newly started background agent task.""" + + agent_id: str + """Generated agent ID for the background task""" + + @staticmethod + def from_dict(obj: Any) -> 'TasksStartAgentResult': + assert isinstance(obj, dict) + agent_id = from_str(obj.get("agentId")) + return TasksStartAgentResult(agent_id) + + def to_dict(self) -> dict: + result: dict = {} + result["agentId"] = from_str(self.agent_id) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksWaitForPendingResult: + """Wait until all in-flight background tasks (agents + shells) and any follow-up turns + scheduled by their completions have settled. Returns when the runtime is fully drained or + after an internal timeout (default 10 minutes; configurable via + COPILOT_TASK_WAIT_TIMEOUT_SECONDS). + """ + @staticmethod + def from_dict(obj: Any) -> 'TasksWaitForPendingResult': + assert isinstance(obj, dict) + return TasksWaitForPendingResult() + + 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 TelemetrySetFeatureOverridesRequest: + """Feature override key/value pairs to attach to subsequent telemetry events from this + session. + """ + features: dict[str, str] + """Override key/value pairs to attach to subsequent telemetry events from this session. + Replaces any previously-set overrides. + """ + + @staticmethod + def from_dict(obj: Any) -> 'TelemetrySetFeatureOverridesRequest': + assert isinstance(obj, dict) + features = from_dict(from_str, obj.get("features")) + return TelemetrySetFeatureOverridesRequest(features) + + def to_dict(self) -> dict: + result: dict = {} + result["features"] = from_dict(from_str, self.features) + return result + +class TokenAuthInfoType(Enum): + TOKEN = "token" + +@dataclass +class Tool: + """Schema for the `Tool` type.""" + + description: str + """Description of what the tool does""" + + name: str + """Tool identifier (e.g., "bash", "grep", "str_replace_editor")""" + + instructions: str | None = None + """Optional instructions for how to use this tool effectively""" + + namespaced_name: str | None = None + """Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP + tools) + """ + parameters: dict[str, Any] | None = None + """JSON Schema for the tool's input parameters""" + + @staticmethod + def from_dict(obj: Any) -> 'Tool': + assert isinstance(obj, dict) + description = from_str(obj.get("description")) + name = from_str(obj.get("name")) + instructions = from_union([from_str, from_none], obj.get("instructions")) + namespaced_name = from_union([from_str, from_none], obj.get("namespacedName")) + parameters = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("parameters")) + return Tool(description, name, instructions, namespaced_name, parameters) + + def to_dict(self) -> dict: + result: dict = {} + result["description"] = from_str(self.description) + result["name"] = from_str(self.name) + if self.instructions is not None: + result["instructions"] = from_union([from_str, from_none], self.instructions) + if self.namespaced_name is not None: + result["namespacedName"] = from_union([from_str, from_none], self.namespaced_name) + if self.parameters is not None: + result["parameters"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.parameters) + return result + +@dataclass +class ToolsInitializeAndValidateResult: + """Resolve, build, and validate the runtime tool list for this session. Subagent sessions + and consumer flows that need an initialized tool set before `send` invoke this. Default + base-class implementation is a no-op for sessions that don't support tool validation. + """ + @staticmethod + def from_dict(obj: Any) -> 'ToolsInitializeAndValidateResult': + assert isinstance(obj, dict) + return ToolsInitializeAndValidateResult() + + def to_dict(self) -> dict: + result: dict = {} + return result + +@dataclass +class ToolsListRequest: + """Optional model identifier whose tool overrides should be applied to the listing.""" + + model: str | None = None + """Optional model ID — when provided, the returned tool list reflects model-specific + overrides + """ + + @staticmethod + def from_dict(obj: Any) -> 'ToolsListRequest': + assert isinstance(obj, dict) + model = from_union([from_str, from_none], obj.get("model")) + return ToolsListRequest(model) + + def to_dict(self) -> dict: + result: dict = {} + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + return result + +class UIAutoModeSwitchResponse(Enum): + """User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist + as setting), or no (decline). + """ + NO = "no" + YES = "yes" + YES_ALWAYS = "yes_always" + +@dataclass +class UIElicitationArrayAnyOfFieldItemsAnyOf: + """Schema for the `UIElicitationArrayAnyOfFieldItemsAnyOf` type.""" + + const: str + """Value submitted when this option is selected.""" + + title: str + """Display label for this option.""" + + @staticmethod + def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItemsAnyOf': + assert isinstance(obj, dict) + const = from_str(obj.get("const")) + title = from_str(obj.get("title")) + return UIElicitationArrayAnyOfFieldItemsAnyOf(const, title) + + def to_dict(self) -> dict: + result: dict = {} + result["const"] = from_str(self.const) + result["title"] = from_str(self.title) + return result + +class UIElicitationArrayAnyOfFieldType(Enum): + ARRAY = "array" + +class UIElicitationArrayEnumFieldItemsType(Enum): + STRING = "string" + +class UIElicitationSchemaPropertyStringFormat(Enum): + """Optional format hint that constrains the accepted input.""" + + DATE = "date" + DATE_TIME = "date-time" + EMAIL = "email" + URI = "uri" + +@dataclass +class UIElicitationStringOneOfFieldOneOf: + """Schema for the `UIElicitationStringOneOfFieldOneOf` type.""" + + const: str + """Value submitted when this option is selected.""" + + title: str + """Display label for this option.""" + + @staticmethod + def from_dict(obj: Any) -> 'UIElicitationStringOneOfFieldOneOf': + assert isinstance(obj, dict) + const = from_str(obj.get("const")) + title = from_str(obj.get("title")) + return UIElicitationStringOneOfFieldOneOf(const, title) + + def to_dict(self) -> dict: + result: dict = {} + result["const"] = from_str(self.const) + result["title"] = from_str(self.title) + return result + +class UIElicitationSchemaPropertyType(Enum): + """Numeric type accepted by the field.""" + + ARRAY = "array" + BOOLEAN = "boolean" + INTEGER = "integer" + NUMBER = "number" + STRING = "string" + +class UIElicitationSchemaType(Enum): + OBJECT = "object" + +class UIElicitationResponseAction(Enum): + """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" + + ACCEPT = "accept" + CANCEL = "cancel" + DECLINE = "decline" + +@dataclass +class UIElicitationResult: + """Indicates whether the elicitation response was accepted; false if it was already resolved + by another client. + """ + success: bool + """Whether the response was accepted. False if the request was already resolved by another + client. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIElicitationResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return UIElicitationResult(success) + + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result + +class UIElicitationSchemaPropertyBooleanType(Enum): + BOOLEAN = "boolean" + +class UIElicitationSchemaPropertyNumberType(Enum): + """Numeric type accepted by the field.""" + + INTEGER = "integer" + NUMBER = "number" + +class UIExitPlanModeAction(Enum): + """The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, + otherwise 'interactive'. + """ + AUTOPILOT = "autopilot" + AUTOPILOT_FLEET = "autopilot_fleet" + EXIT_ONLY = "exit_only" + INTERACTIVE = "interactive" + +@dataclass +class UIHandlePendingResult: + """Indicates whether the pending UI request was resolved by this call.""" + + success: bool + """True if the request was still pending and was resolved by this call. False if the request + ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise + no longer pending. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIHandlePendingResult': + assert isinstance(obj, dict) + success = from_bool(obj.get("success")) + return UIHandlePendingResult(success) + + def to_dict(self) -> dict: + result: dict = {} + result["success"] = from_bool(self.success) + return result + +@dataclass +class UIHandlePendingSamplingRequest: + """Request ID of a pending `sampling.requested` event and an optional sampling result + payload (omit to reject). + """ + request_id: str + """The unique request ID from the sampling.requested event""" + + response: dict[str, Any] | None = None + """Optional sampling result payload. Omit to reject/cancel the sampling request without + providing a result. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIHandlePendingSamplingRequest': + assert isinstance(obj, dict) + request_id = from_str(obj.get("requestId")) + response = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("response")) + return UIHandlePendingSamplingRequest(request_id, response) + + def to_dict(self) -> dict: + result: dict = {} + result["requestId"] = from_str(self.request_id) + if self.response is not None: + result["response"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.response) + return result + +@dataclass +class UIUserInputResponse: + """Schema for the `UIUserInputResponse` type.""" + + answer: str + """The user's answer text""" + + was_freeform: bool + """True if the user typed a freeform response, false if they selected a presented choice. + Used by telemetry to differentiate between free text input and choice selection. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIUserInputResponse': + assert isinstance(obj, dict) + answer = from_str(obj.get("answer")) + was_freeform = from_bool(obj.get("wasFreeform")) + return UIUserInputResponse(answer, was_freeform) + + def to_dict(self) -> dict: + result: dict = {} + result["answer"] = from_str(self.answer) + result["wasFreeform"] = from_bool(self.was_freeform) + return result + +@dataclass +class UIRegisterDirectAutoModeSwitchHandlerResult: + """Register an in-process handler for `auto_mode_switch.requested` events. The caller still + attaches the actual listener via the standard event-subscription mechanism; this + registration solely tells the server bridge to skip its own dispatch (so a remote client + doesn't race the in-process handler for the same requestId). + """ + handle: str + """Opaque handle representing the registration. Pass this same handle to + `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. + Multiple registrations are reference-counted; the server bridge will only dispatch + auto-mode-switch requests when no handles are active. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIRegisterDirectAutoModeSwitchHandlerResult': + assert isinstance(obj, dict) + handle = from_str(obj.get("handle")) + return UIRegisterDirectAutoModeSwitchHandlerResult(handle) + + def to_dict(self) -> dict: + result: dict = {} + result["handle"] = from_str(self.handle) + return result + +@dataclass +class UIUnregisterDirectAutoModeSwitchHandlerRequest: + """Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release.""" + + handle: str + """Handle previously returned by `registerDirectAutoModeSwitchHandler`""" + + @staticmethod + def from_dict(obj: Any) -> 'UIUnregisterDirectAutoModeSwitchHandlerRequest': + assert isinstance(obj, dict) + handle = from_str(obj.get("handle")) + return UIUnregisterDirectAutoModeSwitchHandlerRequest(handle) + + def to_dict(self) -> dict: + result: dict = {} + result["handle"] = from_str(self.handle) + return result + +@dataclass +class UIUnregisterDirectAutoModeSwitchHandlerResult: + """Indicates whether the handle was active and the registration count was decremented.""" + + unregistered: bool + """True if the handle was active and decremented the counter; false if the handle was + unknown. + """ + + @staticmethod + def from_dict(obj: Any) -> 'UIUnregisterDirectAutoModeSwitchHandlerResult': + assert isinstance(obj, dict) + unregistered = from_bool(obj.get("unregistered")) + return UIUnregisterDirectAutoModeSwitchHandlerResult(unregistered) + + def to_dict(self) -> dict: + result: dict = {} + result["unregistered"] = from_bool(self.unregistered) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class UsageMetricsCodeChanges: + """Aggregated code change metrics""" + + files_modified: list[str] + """Distinct file paths modified during the session""" + + 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 = from_list(from_str, obj.get("filesModified")) + 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, files_modified_count, lines_added, lines_removed) + + def to_dict(self) -> dict: + result: dict = {} + result["filesModified"] = from_list(from_str, self.files_modified) + result["filesModifiedCount"] = from_int(self.files_modified_count) + result["linesAdded"] = from_int(self.lines_added) + result["linesRemoved"] = from_int(self.lines_removed) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@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 + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class UsageMetricsModelMetricTokenDetail: + """Schema for the `UsageMetricsModelMetricTokenDetail` type.""" + + token_count: int + """Accumulated token count for this token type""" + + @staticmethod + def from_dict(obj: Any) -> 'UsageMetricsModelMetricTokenDetail': + assert isinstance(obj, dict) + token_count = from_int(obj.get("tokenCount")) + return UsageMetricsModelMetricTokenDetail(token_count) + + def to_dict(self) -> dict: + result: dict = {} + result["tokenCount"] = from_int(self.token_count) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@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 + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class UsageMetricsTokenDetail: + """Schema for the `UsageMetricsTokenDetail` type.""" + + token_count: int + """Accumulated token count for this token type""" + + @staticmethod + def from_dict(obj: Any) -> 'UsageMetricsTokenDetail': + assert isinstance(obj, dict) + token_count = from_int(obj.get("tokenCount")) + return UsageMetricsTokenDetail(token_count) + + def to_dict(self) -> dict: + result: dict = {} + result["tokenCount"] = from_int(self.token_count) + return result + +class UserAuthInfoType(Enum): + USER = "user" + +@dataclass +class WorkspacesCheckpoints: + """Schema for the `WorkspacesCheckpoints` type.""" + + filename: str + """Filename of the checkpoint within the workspace checkpoints directory""" + + number: int + """Checkpoint number assigned by the workspace manager""" + + title: str + """Human-readable checkpoint title""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesCheckpoints': + assert isinstance(obj, dict) + filename = from_str(obj.get("filename")) + number = from_int(obj.get("number")) + title = from_str(obj.get("title")) + return WorkspacesCheckpoints(filename, number, title) + + def to_dict(self) -> dict: + result: dict = {} + result["filename"] = from_str(self.filename) + result["number"] = from_int(self.number) + result["title"] = from_str(self.title) + return result + +@dataclass +class WorkspacesCreateFileRequest: + """Relative path and UTF-8 content for the workspace file to create or overwrite.""" + + content: str + """File content to write as a UTF-8 string""" + + path: str + """Relative path within the workspace files directory""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesCreateFileRequest': + assert isinstance(obj, dict) + content = from_str(obj.get("content")) + path = from_str(obj.get("path")) + return WorkspacesCreateFileRequest(content, path) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_str(self.content) + result["path"] = from_str(self.path) + return result + +@dataclass +class WorkspacesListFilesResult: + """Relative paths of files stored in the session workspace files directory.""" + + files: list[str] + """Relative file paths in the workspace files directory""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesListFilesResult': + assert isinstance(obj, dict) + files = from_list(from_str, obj.get("files")) + return WorkspacesListFilesResult(files) + + def to_dict(self) -> dict: + result: dict = {} + result["files"] = from_list(from_str, self.files) + return result + +@dataclass +class WorkspacesReadCheckpointRequest: + """Checkpoint number to read.""" + + number: int + """Checkpoint number to read""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesReadCheckpointRequest': + assert isinstance(obj, dict) + number = from_int(obj.get("number")) + return WorkspacesReadCheckpointRequest(number) + + def to_dict(self) -> dict: + result: dict = {} + result["number"] = from_int(self.number) + return result + +@dataclass +class WorkspacesReadCheckpointResult: + """Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing.""" + + content: str | None = None + """Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesReadCheckpointResult': + assert isinstance(obj, dict) + content = from_union([from_none, from_str], obj.get("content")) + return WorkspacesReadCheckpointResult(content) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_union([from_none, from_str], self.content) + return result + +@dataclass +class WorkspacesReadFileRequest: + """Relative path of the workspace file to read.""" + + path: str + """Relative path within the workspace files directory""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesReadFileRequest': + assert isinstance(obj, dict) + path = from_str(obj.get("path")) + return WorkspacesReadFileRequest(path) + + def to_dict(self) -> dict: + result: dict = {} + result["path"] = from_str(self.path) + return result + +@dataclass +class WorkspacesReadFileResult: + """Contents of the requested workspace file as a UTF-8 string.""" + + content: str + """File content as a UTF-8 string""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesReadFileResult': + assert isinstance(obj, dict) + content = from_str(obj.get("content")) + return WorkspacesReadFileResult(content) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_str(self.content) + return result + +@dataclass +class WorkspacesSaveLargePasteRequest: + """Pasted content to save as a UTF-8 file in the session workspace.""" + + content: str + """Pasted content to save as a UTF-8 file""" + + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesSaveLargePasteRequest': + assert isinstance(obj, dict) + content = from_str(obj.get("content")) + return WorkspacesSaveLargePasteRequest(content) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_str(self.content) + return result + +@dataclass +class Saved: + filename: str + """Filename within the workspace files directory""" + + file_path: str + """Absolute filesystem path to the saved paste file""" + + size_bytes: int + """Size of the saved file in bytes""" + + @staticmethod + def from_dict(obj: Any) -> 'Saved': + assert isinstance(obj, dict) + filename = from_str(obj.get("filename")) + file_path = from_str(obj.get("filePath")) + size_bytes = from_int(obj.get("sizeBytes")) + return Saved(filename, file_path, size_bytes) + + def to_dict(self) -> dict: + result: dict = {} + result["filename"] = from_str(self.filename) + result["filePath"] = from_str(self.file_path) + result["sizeBytes"] = from_int(self.size_bytes) + return result + +@dataclass +class AccountGetQuotaResult: + """Quota usage snapshots for the resolved user, keyed by quota type.""" + + quota_snapshots: dict[str, AccountQuotaSnapshot] + """Quota snapshots keyed by type (e.g., chat, completions, premium_interactions)""" + + @staticmethod + def from_dict(obj: Any) -> 'AccountGetQuotaResult': + assert isinstance(obj, dict) + quota_snapshots = from_dict(AccountQuotaSnapshot.from_dict, obj.get("quotaSnapshots")) + return AccountGetQuotaResult(quota_snapshots) + + def to_dict(self) -> dict: + result: dict = {} + result["quotaSnapshots"] = from_dict(lambda x: to_class(AccountQuotaSnapshot, x), self.quota_snapshots) + return result + +@dataclass +class SessionAuthStatus: + """Authentication status and account metadata for the session.""" + + is_authenticated: bool + """Whether the session has resolved authentication""" + + auth_type: AuthInfoType | None = None + """Authentication type""" + + copilot_plan: str | None = None + """Copilot plan tier (e.g., individual_pro, business)""" + + host: str | None = None + """Authentication host URL""" + + login: str | None = None + """Authenticated login/username, if available""" + + status_message: str | None = None + """Human-readable authentication status description""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionAuthStatus': + assert isinstance(obj, dict) + is_authenticated = from_bool(obj.get("isAuthenticated")) + auth_type = from_union([AuthInfoType, from_none], obj.get("authType")) + copilot_plan = from_union([from_str, from_none], obj.get("copilotPlan")) + host = from_union([from_str, from_none], obj.get("host")) + login = from_union([from_str, from_none], obj.get("login")) + status_message = from_union([from_str, from_none], obj.get("statusMessage")) + return SessionAuthStatus(is_authenticated, auth_type, copilot_plan, host, login, status_message) + + def to_dict(self) -> dict: + result: dict = {} + result["isAuthenticated"] = from_bool(self.is_authenticated) + if self.auth_type is not None: + result["authType"] = from_union([lambda x: to_enum(AuthInfoType, x), from_none], self.auth_type) + if self.copilot_plan is not None: + result["copilotPlan"] = from_union([from_str, from_none], self.copilot_plan) + if self.host is not None: + result["host"] = from_union([from_str, from_none], self.host) + if self.login is not None: + result["login"] = from_union([from_str, from_none], self.login) + if self.status_message is not None: + result["statusMessage"] = from_union([from_str, from_none], self.status_message) + return result + +@dataclass +class SlashCommandInput: + """Optional unstructured input hint""" + + hint: str + """Hint to display when command input has not been provided""" + + completion: SlashCommandInputCompletion | None = None + """Optional completion hint for the input (e.g. 'directory' for filesystem path completion)""" + + preserve_multiline_input: bool | None = None + """When true, clients should pass the full text after the command name as a single argument + rather than splitting on whitespace + """ + required: bool | None = None + """When true, the command requires non-empty input; clients should render the input hint as + required + """ + + @staticmethod + def from_dict(obj: Any) -> 'SlashCommandInput': + assert isinstance(obj, dict) + hint = from_str(obj.get("hint")) + completion = from_union([SlashCommandInputCompletion, from_none], obj.get("completion")) + preserve_multiline_input = from_union([from_bool, from_none], obj.get("preserveMultilineInput")) + required = from_union([from_bool, from_none], obj.get("required")) + return SlashCommandInput(hint, completion, preserve_multiline_input, required) + + def to_dict(self) -> dict: + result: dict = {} + result["hint"] = from_str(self.hint) + if self.completion is not None: + result["completion"] = from_union([lambda x: to_enum(SlashCommandInputCompletion, x), from_none], self.completion) + if self.preserve_multiline_input is not None: + result["preserveMultilineInput"] = from_union([from_bool, from_none], self.preserve_multiline_input) + if self.required is not None: + result["required"] = from_union([from_bool, from_none], self.required) + return result + +@dataclass +class SendAttachmentDirectory: + """Directory attachment""" + + display_name: str + """User-facing display name for the attachment""" + + path: str + """Absolute directory path""" + + type: SlashCommandInputCompletion + """Attachment type discriminator""" + + @staticmethod + def from_dict(obj: Any) -> 'SendAttachmentDirectory': + assert isinstance(obj, dict) + display_name = from_str(obj.get("displayName")) + path = from_str(obj.get("path")) + type = SlashCommandInputCompletion(obj.get("type")) + return SendAttachmentDirectory(display_name, path, type) + + def to_dict(self) -> dict: + result: dict = {} + result["displayName"] = from_str(self.display_name) + result["path"] = from_str(self.path) + result["type"] = to_enum(SlashCommandInputCompletion, self.type) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ConnectedRemoteSessionMetadata: + """Metadata for a connected remote session.""" + + kind: ConnectedRemoteSessionMetadataKind + """Neutral SDK discriminator for the connected remote session kind.""" + + modified_time: datetime + """Last session update time as an ISO 8601 string.""" + + repository: ConnectedRemoteSessionMetadataRepository + """Repository associated with the connected remote session.""" + + session_id: str + """SDK session ID for the connected remote session.""" + + start_time: datetime + """Session start time as an ISO 8601 string.""" + + name: str | None = None + """Optional friendly session name.""" + + pull_request_number: int | None = None + """Pull request number associated with the session.""" + + resource_id: str | None = None + """Original remote resource identifier.""" + + stale_at: datetime | None = None + """Remote session staleness deadline as an ISO 8601 string.""" + + state: str | None = None + """Remote session state returned by the backing service.""" + + summary: str | None = None + """Optional session summary.""" + + @staticmethod + def from_dict(obj: Any) -> 'ConnectedRemoteSessionMetadata': + assert isinstance(obj, dict) + kind = ConnectedRemoteSessionMetadataKind(obj.get("kind")) + modified_time = from_datetime(obj.get("modifiedTime")) + repository = ConnectedRemoteSessionMetadataRepository.from_dict(obj.get("repository")) + session_id = from_str(obj.get("sessionId")) + start_time = from_datetime(obj.get("startTime")) + name = from_union([from_str, from_none], obj.get("name")) + pull_request_number = from_union([from_int, from_none], obj.get("pullRequestNumber")) + resource_id = from_union([from_str, from_none], obj.get("resourceId")) + stale_at = from_union([from_datetime, from_none], obj.get("staleAt")) + state = from_union([from_str, from_none], obj.get("state")) + summary = from_union([from_str, from_none], obj.get("summary")) + return ConnectedRemoteSessionMetadata(kind, modified_time, repository, session_id, start_time, name, pull_request_number, resource_id, stale_at, state, summary) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(ConnectedRemoteSessionMetadataKind, self.kind) + result["modifiedTime"] = self.modified_time.isoformat() + result["repository"] = to_class(ConnectedRemoteSessionMetadataRepository, self.repository) + result["sessionId"] = from_str(self.session_id) + result["startTime"] = self.start_time.isoformat() + if self.name is not None: + result["name"] = from_union([from_str, from_none], self.name) + if self.pull_request_number is not None: + result["pullRequestNumber"] = from_union([from_int, from_none], self.pull_request_number) + if self.resource_id is not None: + result["resourceId"] = from_union([from_str, from_none], self.resource_id) + if self.stale_at is not None: + result["staleAt"] = from_union([lambda x: x.isoformat(), from_none], self.stale_at) + if self.state is not None: + result["state"] = from_union([from_str, from_none], self.state) + if self.summary is not None: + result["summary"] = from_union([from_str, from_none], self.summary) + return result + +@dataclass +class MCPServerConfigStdio: + """Stdio MCP server configuration launched as a child process.""" + + command: str + """Executable command used to start the Stdio MCP server process.""" + + args: list[str] | None = None + """Command-line arguments passed to the Stdio MCP server process.""" + + cwd: str | None = None + """Working directory for the Stdio MCP server process.""" + + env: dict[str, str] | None = None + """Environment variables to pass to the Stdio MCP server process.""" + + filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None + """Content filtering mode to apply to all tools, or a map of tool name to content filtering + mode. + """ + is_default_server: bool | None = None + """Whether this server is a built-in fallback used when the user has not configured their + own server. + """ + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + + tools: list[str] | None = None + """Tools to include. Defaults to all tools if not specified.""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPServerConfigStdio': + assert isinstance(obj, dict) + command = from_str(obj.get("command")) + args = from_union([lambda x: from_list(from_str, x), from_none], obj.get("args")) + 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(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) + is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) + timeout = from_union([from_int, from_none], obj.get("timeout")) + tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) + return MCPServerConfigStdio(command, args, cwd, env, filter_mapping, is_default_server, timeout, tools) + + def to_dict(self) -> dict: + result: dict = {} + result["command"] = from_str(self.command) + if self.args is not None: + result["args"] = from_union([lambda x: from_list(from_str, x), from_none], self.args) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + 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(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) + if self.is_default_server is not None: + result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) + if self.timeout is not None: + result["timeout"] = from_union([from_int, from_none], self.timeout) + if self.tools is not None: + result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) + return result + +@dataclass +class CopilotUserResponseQuotaSnapshots: + """Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. + + Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. + + Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. + """ + entitlement: float | None = None + has_quota: bool | None = None + overage_count: float | None = None + overage_permitted: bool | None = None + percent_remaining: float | None = None + quota_id: str | None = None + quota_remaining: float | None = None + quota_reset_at: float | None = None + remaining: float | None = None + timestamp_utc: str | None = None + token_based_billing: bool | None = None + unlimited: bool | None = None + + @staticmethod + def from_dict(obj: Any) -> 'CopilotUserResponseQuotaSnapshots': + assert isinstance(obj, dict) + entitlement = from_union([from_float, from_none], obj.get("entitlement")) + has_quota = from_union([from_bool, from_none], obj.get("has_quota")) + overage_count = from_union([from_float, from_none], obj.get("overage_count")) + overage_permitted = from_union([from_bool, from_none], obj.get("overage_permitted")) + percent_remaining = from_union([from_float, from_none], obj.get("percent_remaining")) + quota_id = from_union([from_str, from_none], obj.get("quota_id")) + quota_remaining = from_union([from_float, from_none], obj.get("quota_remaining")) + quota_reset_at = from_union([from_float, from_none], obj.get("quota_reset_at")) + remaining = from_union([from_float, from_none], obj.get("remaining")) + timestamp_utc = from_union([from_str, from_none], obj.get("timestamp_utc")) + token_based_billing = from_union([from_bool, from_none], obj.get("token_based_billing")) + unlimited = from_union([from_bool, from_none], obj.get("unlimited")) + return CopilotUserResponseQuotaSnapshots(entitlement, has_quota, overage_count, overage_permitted, percent_remaining, quota_id, quota_remaining, quota_reset_at, remaining, timestamp_utc, token_based_billing, unlimited) + + def to_dict(self) -> dict: + result: dict = {} + if self.entitlement is not None: + result["entitlement"] = from_union([to_float, from_none], self.entitlement) + if self.has_quota is not None: + result["has_quota"] = from_union([from_bool, from_none], self.has_quota) + if self.overage_count is not None: + result["overage_count"] = from_union([to_float, from_none], self.overage_count) + if self.overage_permitted is not None: + result["overage_permitted"] = from_union([from_bool, from_none], self.overage_permitted) + if self.percent_remaining is not None: + result["percent_remaining"] = from_union([to_float, from_none], self.percent_remaining) + if self.quota_id is not None: + result["quota_id"] = from_union([from_str, from_none], self.quota_id) + if self.quota_remaining is not None: + result["quota_remaining"] = from_union([to_float, from_none], self.quota_remaining) + if self.quota_reset_at is not None: + result["quota_reset_at"] = from_union([to_float, from_none], self.quota_reset_at) + if self.remaining is not None: + result["remaining"] = from_union([to_float, from_none], self.remaining) + if self.timestamp_utc is not None: + result["timestamp_utc"] = from_union([from_str, from_none], self.timestamp_utc) + if self.token_based_billing is not None: + result["token_based_billing"] = from_union([from_bool, from_none], self.token_based_billing) + if self.unlimited is not None: + result["unlimited"] = from_union([from_bool, from_none], self.unlimited) + return result + +@dataclass +class DiscoveredMCPServer: + """Schema for the `DiscoveredMcpServer` type.""" + + enabled: bool + """Whether the server is enabled (not in the disabled list)""" + + name: str + """Server name (config key)""" + + source: McpServerSource + """Configuration source: user, workspace, plugin, or builtin""" + + type: DiscoveredMCPServerType | None = None + """Server transport type: stdio, http, sse, or memory""" + + @staticmethod + def from_dict(obj: Any) -> 'DiscoveredMCPServer': + assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) + name = from_str(obj.get("name")) + source = McpServerSource(obj.get("source")) + type = from_union([DiscoveredMCPServerType, from_none], obj.get("type")) + return DiscoveredMCPServer(enabled, name, source, type) + + def to_dict(self) -> dict: + result: dict = {} + result["enabled"] = from_bool(self.enabled) + result["name"] = from_str(self.name) + result["source"] = to_enum(McpServerSource, self.source) + if self.type is not None: + result["type"] = from_union([lambda x: to_enum(DiscoveredMCPServerType, x), from_none], self.type) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class EventLogReadRequest: + """Cursor, batch size, and optional long-poll/filter parameters for reading session events.""" + + agent_scope: EventsAgentScope | None = None + """Agent-scope filter: 'primary' returns only main-agent events plus events whose type + starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns + events from all agents (matching wildcard-subscription behavior). Default is 'all' to + preserve wildcard semantics for catch-up callers. + """ + cursor: str | None = None + """Opaque cursor returned by a previous read. Omit on the first call to start from the + beginning of the session's persisted history. + """ + max: int | None = None + """Maximum number of events to return in this batch (1–1000, default 200).""" + + types: list[str] | EventLogTypes | None = None + """Either '*' to receive all event types, or a non-empty list of event types to receive""" + + wait_ms: int | None = None + """Milliseconds to wait for new events when the cursor is at the tail of history. 0 + (default) returns immediately even if no events are available. Capped at 30000ms. + Ephemeral events that arrive during the wait are delivered in this batch but are NOT + replayable on a subsequent read (use a non-zero waitMs in your next call to capture + future ephemerals as they happen). + """ + + @staticmethod + def from_dict(obj: Any) -> 'EventLogReadRequest': + assert isinstance(obj, dict) + agent_scope = from_union([EventsAgentScope, from_none], obj.get("agentScope")) + cursor = from_union([from_str, from_none], obj.get("cursor")) + max = from_union([from_int, from_none], obj.get("max")) + types = from_union([lambda x: from_list(from_str, x), EventLogTypes, from_none], obj.get("types")) + wait_ms = from_union([from_int, from_none], obj.get("waitMs")) + return EventLogReadRequest(agent_scope, cursor, max, types, wait_ms) + + def to_dict(self) -> dict: + result: dict = {} + if self.agent_scope is not None: + result["agentScope"] = from_union([lambda x: to_enum(EventsAgentScope, x), from_none], self.agent_scope) + if self.cursor is not None: + result["cursor"] = from_union([from_str, from_none], self.cursor) + if self.max is not None: + result["max"] = from_union([from_int, from_none], self.max) + if self.types is not None: + result["types"] = from_union([lambda x: from_list(from_str, x), lambda x: to_enum(EventLogTypes, x), from_none], self.types) + if self.wait_ms is not None: + result["waitMs"] = from_union([from_int, from_none], self.wait_ms) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class EventsReadResult: + """Batch of session events returned by a read, with cursor and continuation metadata.""" + + cursor: str + """Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue + from where this read left off. Always present, even when no events were returned. + """ + cursor_status: EventsCursorStatus + """Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor + referred to an event that no longer exists in history (e.g. truncated or compacted away) + and the read started from the beginning of the remaining history. + """ + events: list[SessionEvent] + """Events are delivered in two batches per read: persisted events first (in append order), + then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were + empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral + events do not interleave within a single read. + """ + has_more: bool + """True when the read returned `max` events and more events are available immediately. When + false, the next read with a non-zero `waitMs` will block until a new event arrives or the + wait expires. + """ + + @staticmethod + def from_dict(obj: Any) -> 'EventsReadResult': + assert isinstance(obj, dict) + cursor = from_str(obj.get("cursor")) + cursor_status = EventsCursorStatus(obj.get("cursorStatus")) + events = from_list(SessionEvent.from_dict, obj.get("events")) + has_more = from_bool(obj.get("hasMore")) + return EventsReadResult(cursor, cursor_status, events, has_more) + + def to_dict(self) -> dict: + result: dict = {} + result["cursor"] = from_str(self.cursor) + result["cursorStatus"] = to_enum(EventsCursorStatus, self.cursor_status) + result["events"] = from_list(lambda x: to_class(SessionEvent, x), self.events) + result["hasMore"] = from_bool(self.has_more) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class Extension: + """Schema for the `Extension` type.""" + + id: str + """Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper')""" + + name: str + """Extension name (directory name)""" + + source: ExtensionSource + """Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)""" + + status: ExtensionStatus + """Current status: running, disabled, failed, or starting""" + + pid: int | None = None + """Process ID if the extension is running""" + + @staticmethod + def from_dict(obj: Any) -> 'Extension': + assert isinstance(obj, dict) + id = from_str(obj.get("id")) + name = from_str(obj.get("name")) + 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) + + def to_dict(self) -> dict: + result: dict = {} + result["id"] = from_str(self.id) + result["name"] = from_str(self.name) + 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 + +@dataclass +class ExternalToolTextResultForLlmBinaryResultsForLlm: + """Binary result returned by a tool for the model""" + + data: str + """Base64-encoded binary data""" + + mime_type: str + """MIME type of the binary data""" + + type: ExternalToolTextResultForLlmBinaryResultsForLlmType + """Binary result type discriminator. Use "image" for images and "resource" for other binary + data. + """ + description: str | None = None + """Human-readable description of the binary data""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmBinaryResultsForLlm': + assert isinstance(obj, dict) + data = from_str(obj.get("data")) + mime_type = from_str(obj.get("mimeType")) + type = ExternalToolTextResultForLlmBinaryResultsForLlmType(obj.get("type")) + description = from_union([from_str, from_none], obj.get("description")) + return ExternalToolTextResultForLlmBinaryResultsForLlm(data, mime_type, type, description) + + def to_dict(self) -> dict: + result: dict = {} + result["data"] = from_str(self.data) + result["mimeType"] = from_str(self.mime_type) + result["type"] = to_enum(ExternalToolTextResultForLlmBinaryResultsForLlmType, self.type) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + return result + +@dataclass +class ExternalToolTextResultForLlmContentResourceLinkIcon: + """Icon image for a resource""" + + src: str + """URL or path to the icon image""" + + mime_type: str | None = None + """MIME type of the icon image""" + + sizes: list[str] | None = None + """Available icon sizes (e.g., ['16x16', '32x32'])""" + + theme: ExternalToolTextResultForLlmContentResourceLinkIconTheme | None = None + """Theme variant this icon is intended for""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentResourceLinkIcon': + 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([ExternalToolTextResultForLlmContentResourceLinkIconTheme, from_none], obj.get("theme")) + return ExternalToolTextResultForLlmContentResourceLinkIcon(src, mime_type, sizes, theme) + + def to_dict(self) -> dict: + result: dict = {} + result["src"] = from_str(self.src) + if self.mime_type is not None: + result["mimeType"] = from_union([from_str, from_none], self.mime_type) + 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(ExternalToolTextResultForLlmContentResourceLinkIconTheme, x), from_none], self.theme) + return result + +ExternalToolTextResultForLlmContentResourceDetails = EmbeddedTextResourceContents | EmbeddedBlobResourceContents + +@dataclass +class ExternalToolTextResultForLlmContentAudio: + """Audio content block with base64-encoded data""" + + data: str + """Base64-encoded audio data""" + + mime_type: str + """MIME type of the audio (e.g., audio/wav, audio/mpeg)""" + + type: ExternalToolTextResultForLlmContentAudioType + """Content block type discriminator""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentAudio': + assert isinstance(obj, dict) + data = from_str(obj.get("data")) + mime_type = from_str(obj.get("mimeType")) + type = ExternalToolTextResultForLlmContentAudioType(obj.get("type")) + return ExternalToolTextResultForLlmContentAudio(data, mime_type, type) + + def to_dict(self) -> dict: + result: dict = {} + result["data"] = from_str(self.data) + result["mimeType"] = from_str(self.mime_type) + result["type"] = to_enum(ExternalToolTextResultForLlmContentAudioType, self.type) + return result + +@dataclass +class ExternalToolTextResultForLlmContentImage: + """Image content block with base64-encoded data""" + + data: str + """Base64-encoded image data""" + + mime_type: str + """MIME type of the image (e.g., image/png, image/jpeg)""" + + type: ExternalToolTextResultForLlmContentImageType + """Content block type discriminator""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentImage': + assert isinstance(obj, dict) + data = from_str(obj.get("data")) + mime_type = from_str(obj.get("mimeType")) + type = ExternalToolTextResultForLlmContentImageType(obj.get("type")) + return ExternalToolTextResultForLlmContentImage(data, mime_type, type) + + def to_dict(self) -> dict: + result: dict = {} + result["data"] = from_str(self.data) + result["mimeType"] = from_str(self.mime_type) + result["type"] = to_enum(ExternalToolTextResultForLlmContentImageType, self.type) + return result + +@dataclass +class ExternalToolTextResultForLlmContentResource: + """Embedded resource content block with inline text or binary data""" + + resource: ExternalToolTextResultForLlmContentResourceDetails + """The embedded resource contents, either text or base64-encoded binary""" + + type: ExternalToolTextResultForLlmContentResourceType + """Content block type discriminator""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentResource': + assert isinstance(obj, dict) + resource = (lambda x: from_union([EmbeddedTextResourceContents.from_dict, EmbeddedBlobResourceContents.from_dict], x))(obj.get("resource")) + type = ExternalToolTextResultForLlmContentResourceType(obj.get("type")) + return ExternalToolTextResultForLlmContentResource(resource, type) + + def to_dict(self) -> dict: + result: dict = {} + result["resource"] = from_union([lambda x: to_class(EmbeddedTextResourceContents, x), lambda x: to_class(EmbeddedBlobResourceContents, x)], self.resource) + result["type"] = to_enum(ExternalToolTextResultForLlmContentResourceType, self.type) + return result + +@dataclass +class ExternalToolTextResultForLlmContentTerminal: + """Terminal/shell output content block with optional exit code and working directory""" + + text: str + """Terminal/shell output text""" + + type: ExternalToolTextResultForLlmContentTerminalType + """Content block type discriminator""" + + cwd: str | None = None + """Working directory where the command was executed""" + + exit_code: int | None = None + """Process exit code, if the command has completed""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentTerminal': + assert isinstance(obj, dict) + text = from_str(obj.get("text")) + type = ExternalToolTextResultForLlmContentTerminalType(obj.get("type")) + cwd = from_union([from_str, from_none], obj.get("cwd")) + exit_code = from_union([from_int, from_none], obj.get("exitCode")) + return ExternalToolTextResultForLlmContentTerminal(text, type, cwd, exit_code) + + def to_dict(self) -> dict: + result: dict = {} + result["text"] = from_str(self.text) + result["type"] = to_enum(ExternalToolTextResultForLlmContentTerminalType, self.type) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + if self.exit_code is not None: + result["exitCode"] = from_union([from_int, from_none], self.exit_code) + return result + +@dataclass +class ExternalToolTextResultForLlmContentText: + """Plain text content block""" + + text: str + """The text content""" + + type: KindEnum + """Content block type discriminator""" + + @staticmethod + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentText': + assert isinstance(obj, dict) + text = from_str(obj.get("text")) + type = KindEnum(obj.get("type")) + return ExternalToolTextResultForLlmContentText(text, type) + + def to_dict(self) -> dict: + result: dict = {} + result["text"] = from_str(self.text) + result["type"] = to_enum(KindEnum, self.type) + return result + +@dataclass +class SlashCommandTextResult: + """Schema for the `SlashCommandTextResult` type.""" + + kind: KindEnum + """Text result discriminator""" + + text: str + """Text output for the client to render""" + + markdown: bool | None = None + """Whether text contains Markdown""" + + preserve_ansi: bool | None = None + """Whether ANSI sequences should be preserved""" + + runtime_settings_changed: bool | None = None + """True when the invocation mutated user runtime settings; consumers caching settings should + refresh + """ + + @staticmethod + def from_dict(obj: Any) -> 'SlashCommandTextResult': + assert isinstance(obj, dict) + kind = KindEnum(obj.get("kind")) + text = from_str(obj.get("text")) + markdown = from_union([from_bool, from_none], obj.get("markdown")) + preserve_ansi = from_union([from_bool, from_none], obj.get("preserveAnsi")) + runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) + return SlashCommandTextResult(kind, text, markdown, preserve_ansi, runtime_settings_changed) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(KindEnum, self.kind) + result["text"] = from_str(self.text) + if self.markdown is not None: + result["markdown"] = from_union([from_bool, from_none], self.markdown) + if self.preserve_ansi is not None: + result["preserveAnsi"] = from_union([from_bool, from_none], self.preserve_ansi) + if self.runtime_settings_changed is not None: + result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class HistoryCompactResult: + """Compaction outcome with the number of tokens and messages removed, summary text, and the + resulting context window breakdown. + """ + messages_removed: int + """Number of messages removed during compaction""" + + success: bool + """Whether compaction completed successfully""" + + tokens_removed: int + """Number of tokens freed by compaction""" + + context_window: HistoryCompactContextWindow | None = None + """Post-compaction context window usage breakdown""" + + summary_content: str | None = None + """Summary text produced by compaction. Omitted when compaction did not produce a summary + (e.g. failure path). + """ + + @staticmethod + def from_dict(obj: Any) -> 'HistoryCompactResult': + assert isinstance(obj, dict) + messages_removed = from_int(obj.get("messagesRemoved")) + success = from_bool(obj.get("success")) + tokens_removed = from_int(obj.get("tokensRemoved")) + context_window = from_union([HistoryCompactContextWindow.from_dict, from_none], obj.get("contextWindow")) + summary_content = from_union([from_str, from_none], obj.get("summaryContent")) + return HistoryCompactResult(messages_removed, success, tokens_removed, context_window, summary_content) + + def to_dict(self) -> dict: + result: dict = {} + result["messagesRemoved"] = from_int(self.messages_removed) + result["success"] = from_bool(self.success) + result["tokensRemoved"] = from_int(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) + if self.summary_content is not None: + result["summaryContent"] = from_union([from_str, from_none], self.summary_content) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class InstalledPluginSourceGithub: + """Schema for the `InstalledPluginSourceGithub` type.""" + + repo: str + source: FluffySource + """Constant value. Always "github".""" + + path: str | None = None + ref: str | None = None + + @staticmethod + def from_dict(obj: Any) -> 'InstalledPluginSourceGithub': + assert isinstance(obj, dict) + repo = from_str(obj.get("repo")) + source = FluffySource(obj.get("source")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + return InstalledPluginSourceGithub(repo, source, path, ref) + + def to_dict(self) -> dict: + result: dict = {} + result["repo"] = from_str(self.repo) + result["source"] = to_enum(FluffySource, self.source) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionInstalledPluginSourceGithub: + """Schema for the `SessionInstalledPluginSourceGithub` type.""" + + repo: str + source: FluffySource + """Constant value. Always "github".""" + + path: str | None = None + ref: str | None = None + + @staticmethod + def from_dict(obj: Any) -> 'SessionInstalledPluginSourceGithub': + assert isinstance(obj, dict) + repo = from_str(obj.get("repo")) + source = FluffySource(obj.get("source")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + return SessionInstalledPluginSourceGithub(repo, source, path, ref) + + def to_dict(self) -> dict: + result: dict = {} + result["repo"] = from_str(self.repo) + result["source"] = to_enum(FluffySource, self.source) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class InstalledPluginSourceLocal: + """Schema for the `InstalledPluginSourceLocal` type.""" + + path: str + source: TentacledSource + """Constant value. Always "local".""" + + @staticmethod + def from_dict(obj: Any) -> 'InstalledPluginSourceLocal': + assert isinstance(obj, dict) + path = from_str(obj.get("path")) + source = TentacledSource(obj.get("source")) + return InstalledPluginSourceLocal(path, source) + + def to_dict(self) -> dict: + result: dict = {} + result["path"] = from_str(self.path) + result["source"] = to_enum(TentacledSource, self.source) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionInstalledPluginSourceLocal: + """Schema for the `SessionInstalledPluginSourceLocal` type.""" + + path: str + source: TentacledSource + """Constant value. Always "local".""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionInstalledPluginSourceLocal': + assert isinstance(obj, dict) + path = from_str(obj.get("path")) + source = TentacledSource(obj.get("source")) + return SessionInstalledPluginSourceLocal(path, source) + + def to_dict(self) -> dict: + result: dict = {} + result["path"] = from_str(self.path) + result["source"] = to_enum(TentacledSource, self.source) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class InstalledPluginSourceURL: + """Schema for the `InstalledPluginSourceUrl` type.""" + + source: StickySource + """Constant value. Always "url".""" + + url: str + path: str | None = None + ref: str | None = None + + @staticmethod + def from_dict(obj: Any) -> 'InstalledPluginSourceURL': + assert isinstance(obj, dict) + source = StickySource(obj.get("source")) + url = from_str(obj.get("url")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + return InstalledPluginSourceURL(source, url, path, ref) + + def to_dict(self) -> dict: + result: dict = {} + result["source"] = to_enum(StickySource, self.source) + result["url"] = from_str(self.url) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionInstalledPluginSourceURL: + """Schema for the `SessionInstalledPluginSourceUrl` type.""" + + source: StickySource + """Constant value. Always "url".""" + + url: str + path: str | None = None + ref: str | None = None + + @staticmethod + def from_dict(obj: Any) -> 'SessionInstalledPluginSourceURL': + assert isinstance(obj, dict) + source = StickySource(obj.get("source")) + url = from_str(obj.get("url")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + return SessionInstalledPluginSourceURL(source, url, path, ref) + + def to_dict(self) -> dict: + result: dict = {} + result["source"] = to_enum(StickySource, self.source) + result["url"] = from_str(self.url) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + return result + +@dataclass +class InstructionsSources: + """Schema for the `InstructionsSources` type.""" + + content: str + """Raw content of the instruction file""" + + id: str + """Unique identifier for this source (used for toggling)""" + + label: str + """Human-readable label""" + + location: InstructionsSourcesLocation + """Where this source lives — used for UI grouping""" + + source_path: str + """File path relative to repo or absolute for home""" + + type: InstructionsSourcesType + """Category of instruction source — used for merge logic""" + + apply_to: list[str] | None = None + """Glob pattern(s) from frontmatter — when set, this instruction applies only to matching + files + """ + default_disabled: bool | None = None + """When true, this source starts disabled and must be toggled on by the user""" + + description: str | None = None + """Short description (body after frontmatter) for use in instruction tables""" + + @staticmethod + def from_dict(obj: Any) -> 'InstructionsSources': + assert isinstance(obj, dict) + content = from_str(obj.get("content")) + id = from_str(obj.get("id")) + label = from_str(obj.get("label")) + location = InstructionsSourcesLocation(obj.get("location")) + source_path = from_str(obj.get("sourcePath")) + type = InstructionsSourcesType(obj.get("type")) + apply_to = from_union([lambda x: from_list(from_str, x), from_none], obj.get("applyTo")) + default_disabled = from_union([from_bool, from_none], obj.get("defaultDisabled")) + description = from_union([from_str, from_none], obj.get("description")) + return InstructionsSources(content, id, label, location, source_path, type, apply_to, default_disabled, description) + + def to_dict(self) -> dict: + result: dict = {} + result["content"] = from_str(self.content) + result["id"] = from_str(self.id) + result["label"] = from_str(self.label) + result["location"] = to_enum(InstructionsSourcesLocation, self.location) + result["sourcePath"] = from_str(self.source_path) + result["type"] = to_enum(InstructionsSourcesType, self.type) + if self.apply_to is not None: + result["applyTo"] = from_union([lambda x: from_list(from_str, x), from_none], self.apply_to) + if self.default_disabled is not None: + result["defaultDisabled"] = from_union([from_bool, from_none], self.default_disabled) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + return result + +@dataclass +class LogRequest: + """Message text, optional severity level, persistence flag, optional follow-up URL, and + optional tip. + """ + 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: SessionLogLevel | None = None + """Log severity level. Determines how the message is displayed in the timeline. Defaults to + "info". + """ + tip: str | None = None + """Optional actionable tip displayed alongside the message. Only honored on `level: "info"`.""" + + type: str | None = None + """Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps + to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". + """ + url: str | None = None + """Optional URL the user can open in their browser for more details""" + + @staticmethod + 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([SessionLogLevel, from_none], obj.get("level")) + tip = from_union([from_str, from_none], obj.get("tip")) + type = from_union([from_str, from_none], obj.get("type")) + url = from_union([from_str, from_none], obj.get("url")) + return LogRequest(message, ephemeral, level, tip, type, url) + + def to_dict(self) -> dict: + result: dict = {} + result["message"] = from_str(self.message) + 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(SessionLogLevel, x), from_none], self.level) + if self.tip is not None: + result["tip"] = from_union([from_str, from_none], self.tip) + if self.type is not None: + result["type"] = from_union([from_str, from_none], self.type) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) + return result + +@dataclass +class MCPServerConfig: + """MCP server configuration (stdio process or remote HTTP/SSE) + + Stdio MCP server configuration launched as a child process. + + Remote MCP server configuration accessed over HTTP or SSE. + """ + args: list[str] | None = None + """Command-line arguments passed to the Stdio MCP server process.""" + + command: str | None = None + """Executable command used to start the Stdio MCP server process.""" + + cwd: str | None = None + """Working directory for the Stdio MCP server process.""" + + env: dict[str, str] | None = None + """Environment variables to pass to the Stdio MCP server process.""" + + filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None + """Content filtering mode to apply to all tools, or a map of tool name to content filtering + mode. + """ + is_default_server: bool | None = None + """Whether this server is a built-in fallback used when the user has not configured their + own server. + """ + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + + tools: list[str] | None = None + """Tools to include. Defaults to all tools if not specified.""" + + auth: MCPServerConfigHTTPAuth | None = None + """Additional authentication configuration for this server.""" + + headers: dict[str, str] | None = None + """HTTP headers to include in requests to the remote MCP server.""" + + oauth_client_id: str | None = None + """OAuth client ID for a pre-registered remote MCP OAuth client.""" + + oauth_grant_type: MCPServerConfigHTTPOauthGrantType | None = None + """OAuth grant type to use when authenticating to the remote MCP server.""" + + oauth_public_client: bool | None = None + """Whether the configured OAuth client is public and does not require a client secret.""" + + type: MCPServerConfigHTTPType | None = None + """Remote transport type. Defaults to "http" when omitted.""" + + url: str | None = None + """URL of the remote MCP server endpoint.""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPServerConfig': + 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(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) + is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) + timeout = from_union([from_int, from_none], obj.get("timeout")) + tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) + auth = from_union([MCPServerConfigHTTPAuth.from_dict, from_none], obj.get("auth")) + 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_grant_type = from_union([MCPServerConfigHTTPOauthGrantType, from_none], obj.get("oauthGrantType")) + oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) + type = from_union([MCPServerConfigHTTPType, from_none], obj.get("type")) + url = from_union([from_str, from_none], obj.get("url")) + return MCPServerConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, auth, headers, oauth_client_id, oauth_grant_type, oauth_public_client, type, url) + + def to_dict(self) -> dict: + result: dict = {} + if self.args is not None: + result["args"] = from_union([lambda x: from_list(from_str, x), from_none], self.args) + if self.command is not None: + result["command"] = from_union([from_str, from_none], self.command) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + 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(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) + if self.is_default_server is not None: + result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) + if self.timeout is not None: + result["timeout"] = from_union([from_int, from_none], self.timeout) + if self.tools is not None: + result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) + if self.auth is not None: + result["auth"] = from_union([lambda x: to_class(MCPServerConfigHTTPAuth, x), from_none], self.auth) + 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: + result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id) + if self.oauth_grant_type is not None: + result["oauthGrantType"] = from_union([lambda x: to_enum(MCPServerConfigHTTPOauthGrantType, x), from_none], self.oauth_grant_type) + if self.oauth_public_client is not None: + result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client) + if self.type is not None: + result["type"] = from_union([lambda x: to_enum(MCPServerConfigHTTPType, x), from_none], self.type) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) + return result + +@dataclass +class MCPServerConfigHTTP: + """Remote MCP server configuration accessed over HTTP or SSE.""" + + url: str + """URL of the remote MCP server endpoint.""" + + auth: MCPServerConfigHTTPAuth | None = None + """Additional authentication configuration for this server.""" + + filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None + """Content filtering mode to apply to all tools, or a map of tool name to content filtering + mode. + """ + headers: dict[str, str] | None = None + """HTTP headers to include in requests to the remote MCP server.""" + + is_default_server: bool | None = None + """Whether this server is a built-in fallback used when the user has not configured their + own server. + """ + oauth_client_id: str | None = None + """OAuth client ID for a pre-registered remote MCP OAuth client.""" + + oauth_grant_type: MCPServerConfigHTTPOauthGrantType | None = None + """OAuth grant type to use when authenticating to the remote MCP server.""" + + oauth_public_client: bool | None = None + """Whether the configured OAuth client is public and does not require a client secret.""" + + timeout: int | None = None + """Timeout in milliseconds for tool calls to this server.""" + + tools: list[str] | None = None + """Tools to include. Defaults to all tools if not specified.""" + + type: MCPServerConfigHTTPType | None = None + """Remote transport type. Defaults to "http" when omitted.""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPServerConfigHTTP': + assert isinstance(obj, dict) + url = from_str(obj.get("url")) + auth = from_union([MCPServerConfigHTTPAuth.from_dict, from_none], obj.get("auth")) + filter_mapping = from_union([lambda x: from_dict(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) + headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers")) + is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) + oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId")) + oauth_grant_type = from_union([MCPServerConfigHTTPOauthGrantType, from_none], obj.get("oauthGrantType")) + oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) + timeout = from_union([from_int, from_none], obj.get("timeout")) + tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) + type = from_union([MCPServerConfigHTTPType, from_none], obj.get("type")) + return MCPServerConfigHTTP(url, auth, filter_mapping, headers, is_default_server, oauth_client_id, oauth_grant_type, oauth_public_client, timeout, tools, type) + + def to_dict(self) -> dict: + result: dict = {} + result["url"] = from_str(self.url) + if self.auth is not None: + result["auth"] = from_union([lambda x: to_class(MCPServerConfigHTTPAuth, x), from_none], self.auth) + if self.filter_mapping is not None: + result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) + if self.headers is not None: + result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers) + if self.is_default_server is not None: + result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) + if self.oauth_client_id is not None: + result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id) + if self.oauth_grant_type is not None: + result["oauthGrantType"] = from_union([lambda x: to_enum(MCPServerConfigHTTPOauthGrantType, x), from_none], self.oauth_grant_type) + if self.oauth_public_client is not None: + result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client) + if self.timeout is not None: + result["timeout"] = from_union([from_int, from_none], self.timeout) + if self.tools is not None: + result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) + if self.type is not None: + result["type"] = from_union([lambda x: to_enum(MCPServerConfigHTTPType, x), from_none], self.type) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPSamplingExecutionResult: + """Outcome of an MCP sampling execution: success result, failure error, or cancellation.""" + + action: MCPSamplingExecutionAction + """Outcome of the sampling inference. 'success' produced a response; 'failure' encountered + an error (including agent-side rejection by content filter or criteria); 'cancelled' the + caller cancelled this execution via cancelSamplingExecution. + """ + error: str | None = None + """Error description, present when action='failure'.""" + + result: dict[str, Any] | None = None + """MCP CreateMessageResult payload (with optional 'tools' extension), present when + action='success'. Treated as opaque at the schema layer; consumers should + construct/consume it per the MCP CreateMessageResult shape. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MCPSamplingExecutionResult': + assert isinstance(obj, dict) + action = MCPSamplingExecutionAction(obj.get("action")) + error = from_union([from_str, from_none], obj.get("error")) + result = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("result")) + return MCPSamplingExecutionResult(action, error, result) + + def to_dict(self) -> dict: + result: dict = {} + result["action"] = to_enum(MCPSamplingExecutionAction, self.action) + 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: from_dict(lambda x: x, x), from_none], self.result) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPServerList: + """MCP servers configured for the session, with their connection status.""" + + servers: list[MCPServer] + """Configured MCP servers""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPServerList': + assert isinstance(obj, dict) + servers = from_list(MCPServer.from_dict, obj.get("servers")) + return MCPServerList(servers) + + def to_dict(self) -> dict: + result: dict = {} + result["servers"] = from_list(lambda x: to_class(MCPServer, x), self.servers) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPSetEnvValueModeParams: + """Mode controlling how MCP server env values are resolved (`direct` or `indirect`).""" + + mode: MCPSetEnvValueModeDetails + """How environment-variable values supplied to MCP servers are resolved. "direct" passes + literal string values; "indirect" treats values as references (e.g. names of environment + variables on the host) that the runtime resolves before launch. Defaults to the runtime's + startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI + prompt mode and ACP) set this to "direct". + """ + + @staticmethod + def from_dict(obj: Any) -> 'MCPSetEnvValueModeParams': + assert isinstance(obj, dict) + mode = MCPSetEnvValueModeDetails(obj.get("mode")) + return MCPSetEnvValueModeParams(mode) + + def to_dict(self) -> dict: + result: dict = {} + result["mode"] = to_enum(MCPSetEnvValueModeDetails, self.mode) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPSetEnvValueModeResult: + """Env-value mode recorded on the session after the update.""" + + mode: MCPSetEnvValueModeDetails + """Mode recorded on the session after the update""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPSetEnvValueModeResult': + assert isinstance(obj, dict) + mode = MCPSetEnvValueModeDetails(obj.get("mode")) + return MCPSetEnvValueModeResult(mode) + + def to_dict(self) -> dict: + result: dict = {} + result["mode"] = to_enum(MCPSetEnvValueModeDetails, self.mode) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataContextInfoResult: + """Token breakdown for the session's current context window, or null if uninitialized.""" + + context_info: SessionContextInfo | None = None + """Token breakdown for the current context window, or null if the session has not yet been + initialized (no system prompt or tool metadata cached). + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataContextInfoResult': + assert isinstance(obj, dict) + context_info = from_union([SessionContextInfo.from_dict, from_none], obj.get("contextInfo")) + return MetadataContextInfoResult(context_info) + + def to_dict(self) -> dict: + result: dict = {} + if self.context_info is not None: + result["contextInfo"] = from_union([lambda x: to_class(SessionContextInfo, x), from_none], self.context_info) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionWorkingDirectoryContext: + """Updated working directory and git context. Emitted as the new payload of + `session.context_changed`. + """ + cwd: str + """Current working directory path""" + + base_commit: str | None = None + """Merge-base commit SHA (fork point from the remote default branch)""" + + branch: str | None = None + """Current git branch name""" + + git_root: str | None = None + """Root directory of the git repository, resolved via git rev-parse""" + + head_commit: str | None = None + """Head commit of the current git branch""" + + host_type: SessionContextHostType | None = None + """Hosting platform type of the repository""" + + repository: str | None = None + """Repository identifier derived from the git remote URL ("owner/name" for GitHub, + "org/project/repo" for Azure DevOps) + """ + repository_host: str | None = None + """Raw host string from the git remote URL (e.g. "github.com", "dev.azure.com")""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionWorkingDirectoryContext': + 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([SessionContextHostType, from_none], obj.get("hostType")) + repository = from_union([from_str, from_none], obj.get("repository")) + repository_host = from_union([from_str, from_none], obj.get("repositoryHost")) + return SessionWorkingDirectoryContext(cwd, base_commit, branch, git_root, head_commit, host_type, repository, repository_host) + + def to_dict(self) -> dict: + result: dict = {} + result["cwd"] = from_str(self.cwd) + if self.base_commit is not None: + result["baseCommit"] = from_union([from_str, from_none], self.base_commit) + if self.branch is not None: + result["branch"] = from_union([from_str, from_none], self.branch) + if self.git_root is not None: + result["gitRoot"] = from_union([from_str, from_none], self.git_root) + 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(SessionContextHostType, x), from_none], self.host_type) + if self.repository is not None: + result["repository"] = from_union([from_str, from_none], self.repository) + if self.repository_host is not None: + result["repositoryHost"] = from_union([from_str, from_none], self.repository_host) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionContext: + """Schema for the `SessionContext` type. + + Optional working-directory context used to score session relevance. When omitted the + most-recently-modified session wins. + """ + cwd: str + """Most recent working directory for this session""" + + branch: str | None = None + """Active git branch""" + + git_root: str | None = None + """Git repository root, if the cwd was inside a git repo""" + + host_type: SessionContextHostType | None = None + """Repository host type""" + + repository: str | None = None + """Repository slug in `owner/name` form, when known""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionContext': + assert isinstance(obj, dict) + cwd = from_str(obj.get("cwd")) + branch = from_union([from_str, from_none], obj.get("branch")) + git_root = from_union([from_str, from_none], obj.get("gitRoot")) + host_type = from_union([SessionContextHostType, from_none], obj.get("hostType")) + repository = from_union([from_str, from_none], obj.get("repository")) + return SessionContext(cwd, branch, git_root, host_type, repository) + + def to_dict(self) -> dict: + result: dict = {} + result["cwd"] = from_str(self.cwd) + if self.branch is not None: + result["branch"] = from_union([from_str, from_none], self.branch) + if self.git_root is not None: + result["gitRoot"] = from_union([from_str, from_none], self.git_root) + if self.host_type is not None: + result["hostType"] = from_union([lambda x: to_enum(SessionContextHostType, 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 Workspace: + id: UUID + branch: str | None = None + chronicle_sync_dismissed: bool | None = None + created_at: datetime | None = None cwd: str | None = None - """Working directory for the Stdio MCP server process.""" + git_root: str | None = None + host_type: SessionContextHostType | None = None + mc_last_event_id: str | None = None + mc_session_id: str | None = None + mc_task_id: str | None = None + name: str | None = None + remote_steerable: bool | None = None + repository: str | None = None + summary_count: int | None = None + updated_at: datetime | None = None + user_named: bool | None = None + + @staticmethod + def from_dict(obj: Any) -> 'Workspace': + assert isinstance(obj, dict) + id = UUID(obj.get("id")) + branch = from_union([from_str, from_none], obj.get("branch")) + chronicle_sync_dismissed = from_union([from_bool, from_none], obj.get("chronicle_sync_dismissed")) + created_at = from_union([from_datetime, from_none], obj.get("created_at")) + cwd = from_union([from_str, from_none], obj.get("cwd")) + git_root = from_union([from_str, from_none], obj.get("git_root")) + host_type = from_union([SessionContextHostType, from_none], obj.get("host_type")) + mc_last_event_id = from_union([from_str, from_none], obj.get("mc_last_event_id")) + mc_session_id = from_union([from_str, from_none], obj.get("mc_session_id")) + mc_task_id = from_union([from_str, from_none], obj.get("mc_task_id")) + name = from_union([from_str, from_none], obj.get("name")) + remote_steerable = from_union([from_bool, from_none], obj.get("remote_steerable")) + repository = from_union([from_str, from_none], obj.get("repository")) + summary_count = from_union([from_int, from_none], obj.get("summary_count")) + updated_at = from_union([from_datetime, from_none], obj.get("updated_at")) + user_named = from_union([from_bool, from_none], obj.get("user_named")) + return Workspace(id, branch, chronicle_sync_dismissed, created_at, cwd, git_root, host_type, mc_last_event_id, mc_session_id, mc_task_id, name, remote_steerable, repository, summary_count, updated_at, user_named) + + def to_dict(self) -> dict: + result: dict = {} + result["id"] = str(self.id) + if self.branch is not None: + result["branch"] = from_union([from_str, from_none], self.branch) + if self.chronicle_sync_dismissed is not None: + result["chronicle_sync_dismissed"] = from_union([from_bool, from_none], self.chronicle_sync_dismissed) + if self.created_at is not None: + result["created_at"] = from_union([lambda x: x.isoformat(), from_none], self.created_at) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + if self.git_root is not None: + result["git_root"] = from_union([from_str, from_none], self.git_root) + if self.host_type is not None: + result["host_type"] = from_union([lambda x: to_enum(SessionContextHostType, x), from_none], self.host_type) + if self.mc_last_event_id is not None: + result["mc_last_event_id"] = from_union([from_str, from_none], self.mc_last_event_id) + if self.mc_session_id is not None: + result["mc_session_id"] = from_union([from_str, from_none], self.mc_session_id) + if self.mc_task_id is not None: + result["mc_task_id"] = from_union([from_str, from_none], self.mc_task_id) + if self.name is not None: + result["name"] = from_union([from_str, from_none], self.name) + if self.remote_steerable is not None: + result["remote_steerable"] = from_union([from_bool, from_none], self.remote_steerable) + if self.repository is not None: + result["repository"] = from_union([from_str, from_none], self.repository) + if self.summary_count is not None: + result["summary_count"] = from_union([from_int, from_none], self.summary_count) + if self.updated_at is not None: + result["updated_at"] = from_union([lambda x: x.isoformat(), from_none], self.updated_at) + if self.user_named is not None: + result["user_named"] = from_union([from_bool, from_none], self.user_named) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataSnapshotRemoteMetadata: + """Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are + immutable for the lifetime of the session. + """ + repository: MetadataSnapshotRemoteMetadataRepository + """The repository the remote session targets.""" + + pull_request_number: int | None = None + """The pull request number the remote session is associated with, if any.""" + + resource_id: str | None = None + """The original resource identifier (task ID or PR node ID), preserved across event-replay + reconstructions. Falls back to `sessionId` when absent. + """ + task_type: MetadataSnapshotRemoteMetadataTaskType | None = None + """Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` + invocation. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataSnapshotRemoteMetadata': + assert isinstance(obj, dict) + repository = MetadataSnapshotRemoteMetadataRepository.from_dict(obj.get("repository")) + pull_request_number = from_union([from_int, from_none], obj.get("pullRequestNumber")) + resource_id = from_union([from_str, from_none], obj.get("resourceId")) + task_type = from_union([MetadataSnapshotRemoteMetadataTaskType, from_none], obj.get("taskType")) + return MetadataSnapshotRemoteMetadata(repository, pull_request_number, resource_id, task_type) + + def to_dict(self) -> dict: + result: dict = {} + result["repository"] = to_class(MetadataSnapshotRemoteMetadataRepository, self.repository) + if self.pull_request_number is not None: + result["pullRequestNumber"] = from_union([from_int, from_none], self.pull_request_number) + if self.resource_id is not None: + result["resourceId"] = from_union([from_str, from_none], self.resource_id) + if self.task_type is not None: + result["taskType"] = from_union([lambda x: to_enum(MetadataSnapshotRemoteMetadataTaskType, x), from_none], self.task_type) + return result + +@dataclass +class ModelBilling: + """Billing information""" + + multiplier: float | None = None + """Billing cost multiplier relative to the base rate""" + + token_prices: ModelBillingTokenPrices | None = None + """Token-level pricing information for this model""" + + @staticmethod + def from_dict(obj: Any) -> 'ModelBilling': + assert isinstance(obj, dict) + multiplier = from_union([from_float, from_none], obj.get("multiplier")) + token_prices = from_union([ModelBillingTokenPrices.from_dict, from_none], obj.get("tokenPrices")) + return ModelBilling(multiplier, token_prices) + + def to_dict(self) -> dict: + result: dict = {} + if self.multiplier is not None: + result["multiplier"] = from_union([to_float, from_none], self.multiplier) + if self.token_prices is not None: + result["tokenPrices"] = from_union([lambda x: to_class(ModelBillingTokenPrices, x), from_none], self.token_prices) + return result + +@dataclass +class ModelCapabilitiesLimits: + """Token limits for prompts, outputs, and context window""" + + max_context_window_tokens: int | None = None + """Maximum total context window size in tokens""" + + max_output_tokens: int | None = None + """Maximum number of output/completion tokens""" + + max_prompt_tokens: int | None = None + """Maximum number of prompt/input tokens""" + + vision: ModelCapabilitiesLimitsVision | None = None + """Vision-specific limits""" + + @staticmethod + def from_dict(obj: Any) -> 'ModelCapabilitiesLimits': + assert isinstance(obj, dict) + max_context_window_tokens = from_union([from_int, from_none], obj.get("max_context_window_tokens")) + max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) + max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) + vision = from_union([ModelCapabilitiesLimitsVision.from_dict, from_none], obj.get("vision")) + return ModelCapabilitiesLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) + + def to_dict(self) -> dict: + result: dict = {} + if self.max_context_window_tokens is not None: + result["max_context_window_tokens"] = from_union([from_int, from_none], self.max_context_window_tokens) + if self.max_output_tokens is not None: + result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) + if self.max_prompt_tokens is not None: + result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) + if self.vision is not None: + result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesLimitsVision, x), from_none], self.vision) + return result + +@dataclass +class ModelPolicy: + """Policy state (if applicable)""" + + state: ModelPolicyState + """Current policy state for this model""" + + terms: str | None = None + """Usage terms or conditions for this model""" + + @staticmethod + def from_dict(obj: Any) -> 'ModelPolicy': + assert isinstance(obj, dict) + state = ModelPolicyState(obj.get("state")) + terms = from_union([from_str, from_none], obj.get("terms")) + return ModelPolicy(state, terms) + + def to_dict(self) -> dict: + result: dict = {} + result["state"] = to_enum(ModelPolicyState, self.state) + if self.terms is not None: + result["terms"] = from_union([from_str, from_none], self.terms) + return result + +@dataclass +class ModelCapabilitiesOverrideLimits: + """Token limits for prompts, outputs, and context window""" + + max_context_window_tokens: int | None = None + """Maximum total context window size in tokens""" + + max_output_tokens: int | None = None + """Maximum number of output/completion tokens""" + + max_prompt_tokens: int | None = None + """Maximum number of prompt/input tokens""" + + vision: ModelCapabilitiesOverrideLimitsVision | None = None + """Vision-specific limits""" + + @staticmethod + def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimits': + assert isinstance(obj, dict) + max_context_window_tokens = from_union([from_int, from_none], obj.get("max_context_window_tokens")) + max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) + max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) + vision = from_union([ModelCapabilitiesOverrideLimitsVision.from_dict, from_none], obj.get("vision")) + return ModelCapabilitiesOverrideLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) + + def to_dict(self) -> dict: + result: dict = {} + if self.max_context_window_tokens is not None: + result["max_context_window_tokens"] = from_union([from_int, from_none], self.max_context_window_tokens) + if self.max_output_tokens is not None: + result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) + if self.max_prompt_tokens is not None: + result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) + if self.vision is not None: + result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideLimitsVision, x), from_none], self.vision) + return result + +@dataclass +class PendingPermissionRequestList: + """List of pending permission requests reconstructed from event history.""" + + items: list[PendingPermissionRequest] + """Pending permission prompts reconstructed from the session's event history. Equivalent to + the set of `permission.requested` events that have not yet been followed by a matching + `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts + that were emitted before the client attached to the session. + """ + + @staticmethod + def from_dict(obj: Any) -> 'PendingPermissionRequestList': + assert isinstance(obj, dict) + items = from_list(PendingPermissionRequest.from_dict, obj.get("items")) + return PendingPermissionRequestList(items) + + def to_dict(self) -> dict: + result: dict = {} + result["items"] = from_list(lambda x: to_class(PendingPermissionRequest, x), self.items) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalCommands: + """Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type.""" + + command_identifiers: list[str] + """Command identifiers covered by this approval.""" + + kind: PermissionDecisionApproveForLocationApprovalCommandsKind + """Approval scoped to specific command identifiers.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalCommands': + assert isinstance(obj, dict) + command_identifiers = from_list(from_str, obj.get("commandIdentifiers")) + kind = PermissionDecisionApproveForLocationApprovalCommandsKind(obj.get("kind")) + return PermissionDecisionApproveForLocationApprovalCommands(command_identifiers, kind) + + def to_dict(self) -> dict: + result: dict = {} + result["commandIdentifiers"] = from_list(from_str, self.command_identifiers) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCommandsKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalCommands: + """Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type.""" + + command_identifiers: list[str] + """Command identifiers covered by this approval.""" + + kind: PermissionDecisionApproveForLocationApprovalCommandsKind + """Approval scoped to specific command identifiers.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalCommands': + assert isinstance(obj, dict) + command_identifiers = from_list(from_str, obj.get("commandIdentifiers")) + kind = PermissionDecisionApproveForLocationApprovalCommandsKind(obj.get("kind")) + return PermissionDecisionApproveForSessionApprovalCommands(command_identifiers, kind) + + def to_dict(self) -> dict: + result: dict = {} + result["commandIdentifiers"] = from_list(from_str, self.command_identifiers) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCommandsKind, self.kind) + return result + +@dataclass +class UserToolSessionApprovalCommands: + """Schema for the `UserToolSessionApprovalCommands` type.""" + + command_identifiers: list[str] + """Command identifiers approved by the user""" + + kind: PermissionDecisionApproveForLocationApprovalCommandsKind + """Command approval kind""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalCommands': + assert isinstance(obj, dict) + command_identifiers = from_list(from_str, obj.get("commandIdentifiers")) + kind = PermissionDecisionApproveForLocationApprovalCommandsKind(obj.get("kind")) + return UserToolSessionApprovalCommands(command_identifiers, kind) + + def to_dict(self) -> dict: + result: dict = {} + result["commandIdentifiers"] = from_list(from_str, self.command_identifiers) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCommandsKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalCustomTool: + """Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type.""" + + kind: PermissionDecisionApproveForLocationApprovalCustomToolKind + """Approval covering a custom tool.""" + + tool_name: str + """Custom tool name.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalCustomTool': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalCustomToolKind(obj.get("kind")) + tool_name = from_str(obj.get("toolName")) + return PermissionDecisionApproveForLocationApprovalCustomTool(kind, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCustomToolKind, self.kind) + result["toolName"] = from_str(self.tool_name) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalCustomTool: + """Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type.""" + + kind: PermissionDecisionApproveForLocationApprovalCustomToolKind + """Approval covering a custom tool.""" + + tool_name: str + """Custom tool name.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalCustomTool': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalCustomToolKind(obj.get("kind")) + tool_name = from_str(obj.get("toolName")) + return PermissionDecisionApproveForSessionApprovalCustomTool(kind, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCustomToolKind, self.kind) + result["toolName"] = from_str(self.tool_name) + return result + +@dataclass +class UserToolSessionApprovalCustomTool: + """Schema for the `UserToolSessionApprovalCustomTool` type.""" + + kind: PermissionDecisionApproveForLocationApprovalCustomToolKind + """Custom tool approval kind""" + + tool_name: str + """Custom tool name""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalCustomTool': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalCustomToolKind(obj.get("kind")) + tool_name = from_str(obj.get("toolName")) + return UserToolSessionApprovalCustomTool(kind, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCustomToolKind, self.kind) + result["toolName"] = from_str(self.tool_name) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalExtensionManagement: + """Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type.""" + + kind: PermissionDecisionApproveForLocationApprovalExtensionManagementKind + """Approval covering extension lifecycle operations such as enable, disable, or reload.""" + + operation: str | None = None + """Optional operation identifier; when omitted, the approval covers all extension management + operations. + """ + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalExtensionManagement': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalExtensionManagementKind(obj.get("kind")) + operation = from_union([from_str, from_none], obj.get("operation")) + return PermissionDecisionApproveForLocationApprovalExtensionManagement(kind, operation) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionManagementKind, self.kind) + if self.operation is not None: + result["operation"] = from_union([from_str, from_none], self.operation) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalExtensionManagement: + """Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type.""" + + kind: PermissionDecisionApproveForLocationApprovalExtensionManagementKind + """Approval covering extension lifecycle operations such as enable, disable, or reload.""" + + operation: str | None = None + """Optional operation identifier; when omitted, the approval covers all extension management + operations. + """ + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalExtensionManagement': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalExtensionManagementKind(obj.get("kind")) + operation = from_union([from_str, from_none], obj.get("operation")) + return PermissionDecisionApproveForSessionApprovalExtensionManagement(kind, operation) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionManagementKind, self.kind) + if self.operation is not None: + result["operation"] = from_union([from_str, from_none], self.operation) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalMCP: + """Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMCPKind + """Approval covering an MCP tool.""" + + server_name: str + """MCP server name.""" + + tool_name: str | None = None + """MCP tool name, or null to cover every tool on the server.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMCP': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMCPKind(obj.get("kind")) + server_name = from_str(obj.get("serverName")) + tool_name = from_union([from_none, from_str], obj.get("toolName")) + return PermissionDecisionApproveForLocationApprovalMCP(kind, server_name, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPKind, self.kind) + result["serverName"] = from_str(self.server_name) + result["toolName"] = from_union([from_none, from_str], self.tool_name) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalMCP: + """Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMCPKind + """Approval covering an MCP tool.""" + + server_name: str + """MCP server name.""" + + tool_name: str | None = None + """MCP tool name, or null to cover every tool on the server.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMCP': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMCPKind(obj.get("kind")) + server_name = from_str(obj.get("serverName")) + tool_name = from_union([from_none, from_str], obj.get("toolName")) + return PermissionDecisionApproveForSessionApprovalMCP(kind, server_name, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPKind, self.kind) + result["serverName"] = from_str(self.server_name) + result["toolName"] = from_union([from_none, from_str], self.tool_name) + return result + +@dataclass +class UserToolSessionApprovalMCP: + """Schema for the `UserToolSessionApprovalMcp` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMCPKind + """MCP tool approval kind""" + + server_name: str + """MCP server name""" + + tool_name: str | None = None + """Optional MCP tool name, or null for all tools on the server""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalMCP': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMCPKind(obj.get("kind")) + server_name = from_str(obj.get("serverName")) + tool_name = from_union([from_none, from_str], obj.get("toolName")) + return UserToolSessionApprovalMCP(kind, server_name, tool_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPKind, self.kind) + result["serverName"] = from_str(self.server_name) + result["toolName"] = from_union([from_none, from_str], self.tool_name) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalMCPSampling: + """Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMCPSamplingKind + """Approval covering MCP sampling requests for a server.""" + + server_name: str + """MCP server name.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMCPSampling': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMCPSamplingKind(obj.get("kind")) + server_name = from_str(obj.get("serverName")) + return PermissionDecisionApproveForLocationApprovalMCPSampling(kind, server_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPSamplingKind, self.kind) + result["serverName"] = from_str(self.server_name) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalMCPSampling: + """Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMCPSamplingKind + """Approval covering MCP sampling requests for a server.""" + + server_name: str + """MCP server name.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMCPSampling': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMCPSamplingKind(obj.get("kind")) + server_name = from_str(obj.get("serverName")) + return PermissionDecisionApproveForSessionApprovalMCPSampling(kind, server_name) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPSamplingKind, self.kind) + result["serverName"] = from_str(self.server_name) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalMemory: + """Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMemoryKind + """Approval covering writes to long-term memory.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMemory': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMemoryKind(obj.get("kind")) + return PermissionDecisionApproveForLocationApprovalMemory(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMemoryKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalMemory: + """Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMemoryKind + """Approval covering writes to long-term memory.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMemory': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMemoryKind(obj.get("kind")) + return PermissionDecisionApproveForSessionApprovalMemory(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMemoryKind, self.kind) + return result + +@dataclass +class UserToolSessionApprovalMemory: + """Schema for the `UserToolSessionApprovalMemory` type.""" + + kind: PermissionDecisionApproveForLocationApprovalMemoryKind + """Memory approval kind""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalMemory': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalMemoryKind(obj.get("kind")) + return UserToolSessionApprovalMemory(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMemoryKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalRead: + """Schema for the `PermissionDecisionApproveForLocationApprovalRead` type.""" + + kind: PermissionDecisionApproveForLocationApprovalReadKind + """Approval covering read-only filesystem operations.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalRead': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalReadKind(obj.get("kind")) + return PermissionDecisionApproveForLocationApprovalRead(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalReadKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalRead: + """Schema for the `PermissionDecisionApproveForSessionApprovalRead` type.""" + + kind: PermissionDecisionApproveForLocationApprovalReadKind + """Approval covering read-only filesystem operations.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalRead': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalReadKind(obj.get("kind")) + return PermissionDecisionApproveForSessionApprovalRead(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalReadKind, self.kind) + return result + +@dataclass +class UserToolSessionApprovalRead: + """Schema for the `UserToolSessionApprovalRead` type.""" + + kind: PermissionDecisionApproveForLocationApprovalReadKind + """Read approval kind""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalRead': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalReadKind(obj.get("kind")) + return UserToolSessionApprovalRead(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalReadKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForLocationApprovalWrite: + """Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type.""" + + kind: PermissionDecisionApproveForLocationApprovalWriteKind + """Approval covering filesystem write operations.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalWrite': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalWriteKind(obj.get("kind")) + return PermissionDecisionApproveForLocationApprovalWrite(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalWriteKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveForSessionApprovalWrite: + """Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type.""" + + kind: PermissionDecisionApproveForLocationApprovalWriteKind + """Approval covering filesystem write operations.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalWrite': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalWriteKind(obj.get("kind")) + return PermissionDecisionApproveForSessionApprovalWrite(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalWriteKind, self.kind) + return result + +@dataclass +class UserToolSessionApprovalWrite: + """Schema for the `UserToolSessionApprovalWrite` type.""" + + kind: PermissionDecisionApproveForLocationApprovalWriteKind + """Write approval kind""" + + @staticmethod + def from_dict(obj: Any) -> 'UserToolSessionApprovalWrite': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveForLocationApprovalWriteKind(obj.get("kind")) + return UserToolSessionApprovalWrite(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalWriteKind, self.kind) + return result + +@dataclass +class PermissionDecisionApproveOnce: + """Schema for the `PermissionDecisionApproveOnce` type.""" + + kind: PermissionDecisionApproveOnceKind + """Approve this single request only""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveOnce': + assert isinstance(obj, dict) + kind = PermissionDecisionApproveOnceKind(obj.get("kind")) + return PermissionDecisionApproveOnce(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApproveOnceKind, self.kind) + return result - env: dict[str, str] | None = None - """Environment variables to pass to the Stdio MCP server process.""" +@dataclass +class PermissionDecisionApprovePermanently: + """Schema for the `PermissionDecisionApprovePermanently` type.""" - filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None - """Content filtering mode to apply to all tools, or a map of tool name to content filtering - mode. - """ - is_default_server: bool | None = None - """Whether this server is a built-in fallback used when the user has not configured their - own server. - """ - timeout: int | None = None - """Timeout in milliseconds for tool calls to this server.""" + domain: str + """URL domain to approve permanently""" - tools: list[str] | None = None - """Tools to include. Defaults to all tools if not specified.""" + kind: PermissionDecisionApprovePermanentlyKind + """Approve and persist across sessions (URL prompts only)""" - auth: MCPServerConfigHTTPAuth | None = None - """Additional authentication configuration for this server.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApprovePermanently': + assert isinstance(obj, dict) + domain = from_str(obj.get("domain")) + kind = PermissionDecisionApprovePermanentlyKind(obj.get("kind")) + return PermissionDecisionApprovePermanently(domain, kind) - headers: dict[str, str] | None = None - """HTTP headers to include in requests to the remote MCP server.""" + def to_dict(self) -> dict: + result: dict = {} + result["domain"] = from_str(self.domain) + result["kind"] = to_enum(PermissionDecisionApprovePermanentlyKind, self.kind) + return result - oauth_client_id: str | None = None - """OAuth client ID for a pre-registered remote MCP OAuth client.""" +@dataclass +class PermissionDecisionApproved: + """Schema for the `PermissionDecisionApproved` type.""" - oauth_grant_type: MCPServerConfigHTTPOauthGrantType | None = None - """OAuth grant type to use when authenticating to the remote MCP server.""" + kind: PermissionDecisionApprovedKind + """The permission request was approved""" - oauth_public_client: bool | None = None - """Whether the configured OAuth client is public and does not require a client secret.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproved': + assert isinstance(obj, dict) + kind = PermissionDecisionApprovedKind(obj.get("kind")) + return PermissionDecisionApproved(kind) - type: MCPServerConfigHTTPType | None = None - """Remote transport type. Defaults to "http" when omitted.""" + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionApprovedKind, self.kind) + return result - url: str | None = None - """URL of the remote MCP server endpoint.""" +@dataclass +class PermissionDecisionApprovedForLocation: + """Schema for the `PermissionDecisionApprovedForLocation` type.""" + + approval: UserToolSessionApproval + """The approval to persist for this location""" + + kind: PermissionDecisionApprovedForLocationKind + """Approved and persisted for this project location""" + + location_key: str + """The location key (git root or cwd) to persist the approval to""" @staticmethod - def from_dict(obj: Any) -> 'MCPServerConfig': + def from_dict(obj: Any) -> 'PermissionDecisionApprovedForLocation': 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(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) - is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - timeout = from_union([from_int, from_none], obj.get("timeout")) - tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - auth = from_union([MCPServerConfigHTTPAuth.from_dict, from_none], obj.get("auth")) - 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_grant_type = from_union([MCPServerConfigHTTPOauthGrantType, from_none], obj.get("oauthGrantType")) - oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) - type = from_union([MCPServerConfigHTTPType, from_none], obj.get("type")) - url = from_union([from_str, from_none], obj.get("url")) - return MCPServerConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, auth, headers, oauth_client_id, oauth_grant_type, oauth_public_client, type, url) + approval = UserToolSessionApproval.from_dict(obj.get("approval")) + kind = PermissionDecisionApprovedForLocationKind(obj.get("kind")) + location_key = from_str(obj.get("locationKey")) + return PermissionDecisionApprovedForLocation(approval, kind, location_key) def to_dict(self) -> dict: result: dict = {} - if self.args is not None: - result["args"] = from_union([lambda x: from_list(from_str, x), from_none], self.args) - if self.command is not None: - result["command"] = from_union([from_str, from_none], self.command) - if self.cwd is not None: - result["cwd"] = from_union([from_str, from_none], self.cwd) - 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(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) - if self.is_default_server is not None: - result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) - if self.timeout is not None: - result["timeout"] = from_union([from_int, from_none], self.timeout) - if self.tools is not None: - result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) - if self.auth is not None: - result["auth"] = from_union([lambda x: to_class(MCPServerConfigHTTPAuth, x), from_none], self.auth) - 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: - result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id) - if self.oauth_grant_type is not None: - result["oauthGrantType"] = from_union([lambda x: to_enum(MCPServerConfigHTTPOauthGrantType, x), from_none], self.oauth_grant_type) - if self.oauth_public_client is not None: - result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client) - if self.type is not None: - result["type"] = from_union([lambda x: to_enum(MCPServerConfigHTTPType, x), from_none], self.type) - if self.url is not None: - result["url"] = from_union([from_str, from_none], self.url) + result["approval"] = to_class(UserToolSessionApproval, self.approval) + result["kind"] = to_enum(PermissionDecisionApprovedForLocationKind, self.kind) + result["locationKey"] = from_str(self.location_key) return result @dataclass -class MCPServerConfigHTTP: - """Remote MCP server configuration accessed over HTTP or SSE.""" +class PermissionDecisionApprovedForSession: + """Schema for the `PermissionDecisionApprovedForSession` type.""" - url: str - """URL of the remote MCP server endpoint.""" + approval: UserToolSessionApproval + """The approval to add as a session-scoped rule""" - auth: MCPServerConfigHTTPAuth | None = None - """Additional authentication configuration for this server.""" + kind: PermissionDecisionApprovedForSessionKind + """Approved and remembered for the rest of the session""" - filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode | None = None - """Content filtering mode to apply to all tools, or a map of tool name to content filtering - mode. - """ - headers: dict[str, str] | None = None - """HTTP headers to include in requests to the remote MCP server.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApprovedForSession': + assert isinstance(obj, dict) + approval = UserToolSessionApproval.from_dict(obj.get("approval")) + kind = PermissionDecisionApprovedForSessionKind(obj.get("kind")) + return PermissionDecisionApprovedForSession(approval, kind) + + def to_dict(self) -> dict: + result: dict = {} + result["approval"] = to_class(UserToolSessionApproval, self.approval) + result["kind"] = to_enum(PermissionDecisionApprovedForSessionKind, self.kind) + return result + +@dataclass +class PermissionDecisionCancelled: + """Schema for the `PermissionDecisionCancelled` type.""" + + kind: PermissionDecisionCancelledKind + """The permission request was cancelled before a response was used""" + + reason: str | None = None + """Optional explanation of why the request was cancelled""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionCancelled': + assert isinstance(obj, dict) + kind = PermissionDecisionCancelledKind(obj.get("kind")) + reason = from_union([from_str, from_none], obj.get("reason")) + return PermissionDecisionCancelled(kind, reason) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionCancelledKind, self.kind) + if self.reason is not None: + result["reason"] = from_union([from_str, from_none], self.reason) + return result + +@dataclass +class PermissionDecisionDeniedByContentExclusionPolicy: + """Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type.""" + + kind: PermissionDecisionDeniedByContentExclusionPolicyKind + """Denied by the organization's content exclusion policy""" + + message: str + """Human-readable explanation of why the path was excluded""" + + path: str + """File path that triggered the exclusion""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionDeniedByContentExclusionPolicy': + assert isinstance(obj, dict) + kind = PermissionDecisionDeniedByContentExclusionPolicyKind(obj.get("kind")) + message = from_str(obj.get("message")) + path = from_str(obj.get("path")) + return PermissionDecisionDeniedByContentExclusionPolicy(kind, message, path) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionDeniedByContentExclusionPolicyKind, self.kind) + result["message"] = from_str(self.message) + result["path"] = from_str(self.path) + return result + +@dataclass +class PermissionDecisionDeniedByPermissionRequestHook: + """Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type.""" + + kind: PermissionDecisionDeniedByPermissionRequestHookKind + """Denied by a permission request hook registered by an extension or plugin""" + + interrupt: bool | None = None + """Whether to interrupt the current agent turn""" + + message: str | None = None + """Optional message from the hook explaining the denial""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionDeniedByPermissionRequestHook': + assert isinstance(obj, dict) + kind = PermissionDecisionDeniedByPermissionRequestHookKind(obj.get("kind")) + interrupt = from_union([from_bool, from_none], obj.get("interrupt")) + message = from_union([from_str, from_none], obj.get("message")) + return PermissionDecisionDeniedByPermissionRequestHook(kind, interrupt, message) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionDeniedByPermissionRequestHookKind, self.kind) + if self.interrupt is not None: + result["interrupt"] = from_union([from_bool, from_none], self.interrupt) + if self.message is not None: + result["message"] = from_union([from_str, from_none], self.message) + return result + +@dataclass +class PermissionDecisionDeniedByRules: + """Schema for the `PermissionDecisionDeniedByRules` type.""" + + kind: PermissionDecisionDeniedByRulesKind + """Denied because approval rules explicitly blocked it""" + + rules: list[PermissionRule] + """Rules that denied the request""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionDeniedByRules': + assert isinstance(obj, dict) + kind = PermissionDecisionDeniedByRulesKind(obj.get("kind")) + rules = from_list(PermissionRule.from_dict, obj.get("rules")) + return PermissionDecisionDeniedByRules(kind, rules) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionDeniedByRulesKind, self.kind) + result["rules"] = from_list(lambda x: to_class(PermissionRule, x), self.rules) + return result + +@dataclass +class PermissionDecisionDeniedInteractivelyByUser: + """Schema for the `PermissionDecisionDeniedInteractivelyByUser` type.""" + + kind: PermissionDecisionDeniedInteractivelyByUserKind + """Denied by the user during an interactive prompt""" + + feedback: str | None = None + """Optional feedback from the user explaining the denial""" + + force_reject: bool | None = None + """Whether to force-reject the current agent turn""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionDeniedInteractivelyByUser': + assert isinstance(obj, dict) + kind = PermissionDecisionDeniedInteractivelyByUserKind(obj.get("kind")) + feedback = from_union([from_str, from_none], obj.get("feedback")) + force_reject = from_union([from_bool, from_none], obj.get("forceReject")) + return PermissionDecisionDeniedInteractivelyByUser(kind, feedback, force_reject) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionDeniedInteractivelyByUserKind, self.kind) + if self.feedback is not None: + result["feedback"] = from_union([from_str, from_none], self.feedback) + if self.force_reject is not None: + result["forceReject"] = from_union([from_bool, from_none], self.force_reject) + return result + +@dataclass +class PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser: + """Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type.""" + + kind: PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind + """Denied because no approval rule matched and user confirmation was unavailable""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser': + assert isinstance(obj, dict) + kind = PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind(obj.get("kind")) + return PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind, self.kind) + return result + +@dataclass +class PermissionDecisionReject: + """Schema for the `PermissionDecisionReject` type.""" + + kind: PermissionDecisionRejectKind + """Reject the request""" + + feedback: str | None = None + """Optional feedback explaining the rejection""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionReject': + assert isinstance(obj, dict) + kind = PermissionDecisionRejectKind(obj.get("kind")) + feedback = from_union([from_str, from_none], obj.get("feedback")) + return PermissionDecisionReject(kind, feedback) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionRejectKind, self.kind) + if self.feedback is not None: + result["feedback"] = from_union([from_str, from_none], self.feedback) + return result + +@dataclass +class PermissionDecisionUserNotAvailable: + """Schema for the `PermissionDecisionUserNotAvailable` type.""" + + kind: PermissionDecisionUserNotAvailableKind + """No user is available to confirm the request""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionUserNotAvailable': + assert isinstance(obj, dict) + kind = PermissionDecisionUserNotAvailableKind(obj.get("kind")) + return PermissionDecisionUserNotAvailable(kind) + + def to_dict(self) -> dict: + result: dict = {} + result["kind"] = to_enum(PermissionDecisionUserNotAvailableKind, self.kind) + return result + +@dataclass +class PermissionsConfigureAdditionalContentExclusionPolicyRule: + """Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type.""" - is_default_server: bool | None = None - """Whether this server is a built-in fallback used when the user has not configured their - own server. - """ - oauth_client_id: str | None = None - """OAuth client ID for a pre-registered remote MCP OAuth client.""" + paths: list[str] + source: PermissionsConfigureAdditionalContentExclusionPolicyRuleSource + """Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type.""" - oauth_grant_type: MCPServerConfigHTTPOauthGrantType | None = None - """OAuth grant type to use when authenticating to the remote MCP server.""" + if_any_match: list[str] | None = None + if_none_match: list[str] | None = None - oauth_public_client: bool | None = None - """Whether the configured OAuth client is public and does not require a client secret.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionsConfigureAdditionalContentExclusionPolicyRule': + assert isinstance(obj, dict) + paths = from_list(from_str, obj.get("paths")) + source = PermissionsConfigureAdditionalContentExclusionPolicyRuleSource.from_dict(obj.get("source")) + if_any_match = from_union([lambda x: from_list(from_str, x), from_none], obj.get("ifAnyMatch")) + if_none_match = from_union([lambda x: from_list(from_str, x), from_none], obj.get("ifNoneMatch")) + return PermissionsConfigureAdditionalContentExclusionPolicyRule(paths, source, if_any_match, if_none_match) - timeout: int | None = None - """Timeout in milliseconds for tool calls to this server.""" + def to_dict(self) -> dict: + result: dict = {} + result["paths"] = from_list(from_str, self.paths) + result["source"] = to_class(PermissionsConfigureAdditionalContentExclusionPolicyRuleSource, self.source) + if self.if_any_match is not None: + result["ifAnyMatch"] = from_union([lambda x: from_list(from_str, x), from_none], self.if_any_match) + if self.if_none_match is not None: + result["ifNoneMatch"] = from_union([lambda x: from_list(from_str, x), from_none], self.if_none_match) + return result - tools: list[str] | None = None - """Tools to include. Defaults to all tools if not specified.""" +@dataclass +class PermissionsModifyRulesParams: + """Scope and add/remove instructions for modifying session- or location-scoped permission + rules. + """ + scope: PermissionsModifyRulesScope + """Whether the change applies to ephemeral session-scoped rules (cleared at session end) or + to location-scoped rules persisted via the location-permissions config file. + """ + add: list[PermissionRule] | None = None + """Rules to add to the scope. Applied before `remove`/`removeAll`.""" - type: MCPServerConfigHTTPType | None = None - """Remote transport type. Defaults to "http" when omitted.""" + remove: list[PermissionRule] | None = None + """Specific rules to remove from the scope. Ignored when `removeAll` is true.""" + + remove_all: bool | None = None + """When true, removes every rule currently in the scope (after any `add` is applied). Useful + for clearing the location scope wholesale. + """ @staticmethod - def from_dict(obj: Any) -> 'MCPServerConfigHTTP': + def from_dict(obj: Any) -> 'PermissionsModifyRulesParams': assert isinstance(obj, dict) - url = from_str(obj.get("url")) - auth = from_union([MCPServerConfigHTTPAuth.from_dict, from_none], obj.get("auth")) - filter_mapping = from_union([lambda x: from_dict(ContentFilterMode, x), ContentFilterMode, from_none], obj.get("filterMapping")) - headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers")) - is_default_server = from_union([from_bool, from_none], obj.get("isDefaultServer")) - oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId")) - oauth_grant_type = from_union([MCPServerConfigHTTPOauthGrantType, from_none], obj.get("oauthGrantType")) - oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient")) - timeout = from_union([from_int, from_none], obj.get("timeout")) - tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) - type = from_union([MCPServerConfigHTTPType, from_none], obj.get("type")) - return MCPServerConfigHTTP(url, auth, filter_mapping, headers, is_default_server, oauth_client_id, oauth_grant_type, oauth_public_client, timeout, tools, type) + scope = PermissionsModifyRulesScope(obj.get("scope")) + add = from_union([lambda x: from_list(PermissionRule.from_dict, x), from_none], obj.get("add")) + remove = from_union([lambda x: from_list(PermissionRule.from_dict, x), from_none], obj.get("remove")) + remove_all = from_union([from_bool, from_none], obj.get("removeAll")) + return PermissionsModifyRulesParams(scope, add, remove, remove_all) def to_dict(self) -> dict: result: dict = {} - result["url"] = from_str(self.url) - if self.auth is not None: - result["auth"] = from_union([lambda x: to_class(MCPServerConfigHTTPAuth, x), from_none], self.auth) - if self.filter_mapping is not None: - result["filterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x), from_none], self.filter_mapping) - if self.headers is not None: - result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers) - if self.is_default_server is not None: - result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server) - if self.oauth_client_id is not None: - result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id) - if self.oauth_grant_type is not None: - result["oauthGrantType"] = from_union([lambda x: to_enum(MCPServerConfigHTTPOauthGrantType, x), from_none], self.oauth_grant_type) - if self.oauth_public_client is not None: - result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client) - if self.timeout is not None: - result["timeout"] = from_union([from_int, from_none], self.timeout) - if self.tools is not None: - result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) - if self.type is not None: - result["type"] = from_union([lambda x: to_enum(MCPServerConfigHTTPType, x), from_none], self.type) + result["scope"] = to_enum(PermissionsModifyRulesScope, self.scope) + if self.add is not None: + result["add"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRule, x), x), from_none], self.add) + if self.remove is not None: + result["remove"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRule, x), x), from_none], self.remove) + if self.remove_all is not None: + result["removeAll"] = from_union([from_bool, from_none], self.remove_all) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class MCPServerList: - """MCP servers configured for the session, with their connection status.""" +class PluginList: + """Plugins installed for the session, with their enabled state and version metadata.""" - servers: list[MCPServer] - """Configured MCP servers""" + plugins: list[Plugin] + """Installed plugins""" @staticmethod - def from_dict(obj: Any) -> 'MCPServerList': + def from_dict(obj: Any) -> 'PluginList': assert isinstance(obj, dict) - servers = from_list(MCPServer.from_dict, obj.get("servers")) - return MCPServerList(servers) + plugins = from_list(Plugin.from_dict, obj.get("plugins")) + return PluginList(plugins) def to_dict(self) -> dict: result: dict = {} - result["servers"] = from_list(lambda x: to_class(MCPServer, x), self.servers) + result["plugins"] = from_list(lambda x: to_class(Plugin, x), self.plugins) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ModelBilling: - """Billing information""" +class QueuePendingItems: + """Schema for the `QueuePendingItems` type.""" - multiplier: float | None = None - """Billing cost multiplier relative to the base rate""" + display_text: str + """Human-readable text to display for this queue entry in the UI""" - token_prices: ModelBillingTokenPrices | None = None - """Token-level pricing information for this model""" + kind: QueuePendingItemsKind + """Whether this item is a queued user message or a queued slash command / model change""" @staticmethod - def from_dict(obj: Any) -> 'ModelBilling': + def from_dict(obj: Any) -> 'QueuePendingItems': assert isinstance(obj, dict) - multiplier = from_union([from_float, from_none], obj.get("multiplier")) - token_prices = from_union([ModelBillingTokenPrices.from_dict, from_none], obj.get("tokenPrices")) - return ModelBilling(multiplier, token_prices) + display_text = from_str(obj.get("displayText")) + kind = QueuePendingItemsKind(obj.get("kind")) + return QueuePendingItems(display_text, kind) def to_dict(self) -> dict: result: dict = {} - if self.multiplier is not None: - result["multiplier"] = from_union([to_float, from_none], self.multiplier) - if self.token_prices is not None: - result["tokenPrices"] = from_union([lambda x: to_class(ModelBillingTokenPrices, x), from_none], self.token_prices) + result["displayText"] = from_str(self.display_text) + result["kind"] = to_enum(QueuePendingItemsKind, self.kind) return result @dataclass -class ModelCapabilitiesLimits: - """Token limits for prompts, outputs, and context window""" - - max_context_window_tokens: int | None = None - """Maximum total context window size in tokens""" +class QueuedCommandResult: + """Result of the queued command execution. - max_output_tokens: int | None = None - """Maximum number of output/completion tokens""" + Schema for the `QueuedCommandHandled` type. - max_prompt_tokens: int | None = None - """Maximum number of prompt/input tokens""" + Schema for the `QueuedCommandNotHandled` type. + """ + handled: bool + """The host actually executed the queued command. - vision: ModelCapabilitiesLimitsVision | None = None - """Vision-specific limits""" + The host did not execute the queued command. Unblocks the queue without claiming the + command was processed (e.g. when the handler threw before completing). + """ + stop_processing_queue: bool | None = None + """When true, the runtime will not process subsequent queued commands until a new request + comes in. + """ @staticmethod - def from_dict(obj: Any) -> 'ModelCapabilitiesLimits': + def from_dict(obj: Any) -> 'QueuedCommandResult': assert isinstance(obj, dict) - max_context_window_tokens = from_union([from_int, from_none], obj.get("max_context_window_tokens")) - max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) - max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) - vision = from_union([ModelCapabilitiesLimitsVision.from_dict, from_none], obj.get("vision")) - return ModelCapabilitiesLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) + handled = from_bool(obj.get("handled")) + stop_processing_queue = from_union([from_bool, from_none], obj.get("stopProcessingQueue")) + return QueuedCommandResult(handled, stop_processing_queue) def to_dict(self) -> dict: result: dict = {} - if self.max_context_window_tokens is not None: - result["max_context_window_tokens"] = from_union([from_int, from_none], self.max_context_window_tokens) - if self.max_output_tokens is not None: - result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) - if self.max_prompt_tokens is not None: - result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) - if self.vision is not None: - result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesLimitsVision, x), from_none], self.vision) + result["handled"] = from_bool(self.handled) + if self.stop_processing_queue is not None: + result["stopProcessingQueue"] = from_union([from_bool, from_none], self.stop_processing_queue) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ModelPolicy: - """Policy state (if applicable)""" +class RemoteEnableRequest: + """Optional remote session mode ("off", "export", or "on"); defaults to enabling both export + and remote steering. + """ + mode: RemoteSessionMode | None = None + """Per-session remote mode. "off" disables remote, "export" exports session events to GitHub + without enabling remote steering, "on" enables both export and remote steering. + """ - state: ModelPolicyState - """Current policy state for this model""" + @staticmethod + def from_dict(obj: Any) -> 'RemoteEnableRequest': + assert isinstance(obj, dict) + mode = from_union([RemoteSessionMode, from_none], obj.get("mode")) + return RemoteEnableRequest(mode) - terms: str | None = None - """Usage terms or conditions for this model""" + def to_dict(self) -> dict: + result: dict = {} + if self.mode is not None: + result["mode"] = from_union([lambda x: to_enum(RemoteSessionMode, x), from_none], self.mode) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ScheduleList: + """Snapshot of the currently active recurring prompts for this session.""" + + entries: list[ScheduleEntry] + """Active scheduled prompts, ordered by id.""" @staticmethod - def from_dict(obj: Any) -> 'ModelPolicy': + def from_dict(obj: Any) -> 'ScheduleList': assert isinstance(obj, dict) - state = ModelPolicyState(obj.get("state")) - terms = from_union([from_str, from_none], obj.get("terms")) - return ModelPolicy(state, terms) + entries = from_list(ScheduleEntry.from_dict, obj.get("entries")) + return ScheduleList(entries) def to_dict(self) -> dict: result: dict = {} - result["state"] = to_enum(ModelPolicyState, self.state) - if self.terms is not None: - result["terms"] = from_union([from_str, from_none], self.terms) + result["entries"] = from_list(lambda x: to_class(ScheduleEntry, x), self.entries) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ModelCapabilitiesOverrideLimits: - """Token limits for prompts, outputs, and context window""" +class ScheduleStopResult: + """Remove a scheduled prompt by id. The result entry is omitted if the id was unknown.""" - max_context_window_tokens: int | None = None - """Maximum total context window size in tokens""" + entry: ScheduleEntry | None = None + """The removed entry, or omitted if no entry matched.""" - max_output_tokens: int | None = None - """Maximum number of output/completion tokens""" + @staticmethod + def from_dict(obj: Any) -> 'ScheduleStopResult': + assert isinstance(obj, dict) + entry = from_union([ScheduleEntry.from_dict, from_none], obj.get("entry")) + return ScheduleStopResult(entry) - max_prompt_tokens: int | None = None - """Maximum number of prompt/input tokens""" + def to_dict(self) -> dict: + result: dict = {} + if self.entry is not None: + result["entry"] = from_union([lambda x: to_class(ScheduleEntry, x), from_none], self.entry) + return result - vision: ModelCapabilitiesOverrideLimitsVision | None = None - """Vision-specific limits""" +@dataclass +class SendAttachmentSelectionDetails: + """Position range of the selection within the file""" + + end: SendAttachmentSelectionDetailsEnd + """End position of the selection""" + + start: SendAttachmentSelectionDetailsStart + """Start position of the selection""" @staticmethod - def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimits': + def from_dict(obj: Any) -> 'SendAttachmentSelectionDetails': assert isinstance(obj, dict) - max_context_window_tokens = from_union([from_int, from_none], obj.get("max_context_window_tokens")) - max_output_tokens = from_union([from_int, from_none], obj.get("max_output_tokens")) - max_prompt_tokens = from_union([from_int, from_none], obj.get("max_prompt_tokens")) - vision = from_union([ModelCapabilitiesOverrideLimitsVision.from_dict, from_none], obj.get("vision")) - return ModelCapabilitiesOverrideLimits(max_context_window_tokens, max_output_tokens, max_prompt_tokens, vision) + end = SendAttachmentSelectionDetailsEnd.from_dict(obj.get("end")) + start = SendAttachmentSelectionDetailsStart.from_dict(obj.get("start")) + return SendAttachmentSelectionDetails(end, start) def to_dict(self) -> dict: result: dict = {} - if self.max_context_window_tokens is not None: - result["max_context_window_tokens"] = from_union([from_int, from_none], self.max_context_window_tokens) - if self.max_output_tokens is not None: - result["max_output_tokens"] = from_union([from_int, from_none], self.max_output_tokens) - if self.max_prompt_tokens is not None: - result["max_prompt_tokens"] = from_union([from_int, from_none], self.max_prompt_tokens) - if self.vision is not None: - result["vision"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideLimitsVision, x), from_none], self.vision) + result["end"] = to_class(SendAttachmentSelectionDetailsEnd, self.end) + result["start"] = to_class(SendAttachmentSelectionDetailsStart, self.start) return result @dataclass -class PermissionDecisionApproveForLocationApprovalCommands: - """Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type.""" +class SendAttachmentBlob: + """Blob attachment with inline base64-encoded data""" - command_identifiers: list[str] - """Command identifiers covered by this approval.""" + data: str + """Base64-encoded content""" - kind: PermissionDecisionApproveForLocationApprovalCommandsKind - """Approval scoped to specific command identifiers.""" + mime_type: str + """MIME type of the inline data""" + + type: SendAttachmentBlobType + """Attachment type discriminator""" + + display_name: str | None = None + """User-facing display name for the attachment""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalCommands': + def from_dict(obj: Any) -> 'SendAttachmentBlob': assert isinstance(obj, dict) - command_identifiers = from_list(from_str, obj.get("commandIdentifiers")) - kind = PermissionDecisionApproveForLocationApprovalCommandsKind(obj.get("kind")) - return PermissionDecisionApproveForLocationApprovalCommands(command_identifiers, kind) + data = from_str(obj.get("data")) + mime_type = from_str(obj.get("mimeType")) + type = SendAttachmentBlobType(obj.get("type")) + display_name = from_union([from_str, from_none], obj.get("displayName")) + return SendAttachmentBlob(data, mime_type, type, display_name) def to_dict(self) -> dict: result: dict = {} - result["commandIdentifiers"] = from_list(from_str, self.command_identifiers) - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCommandsKind, self.kind) + result["data"] = from_str(self.data) + result["mimeType"] = from_str(self.mime_type) + result["type"] = to_enum(SendAttachmentBlobType, self.type) + if self.display_name is not None: + result["displayName"] = from_union([from_str, from_none], self.display_name) return result @dataclass -class PermissionDecisionApproveForSessionApprovalCommands: - """Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type.""" +class SendAttachmentFile: + """File attachment""" - command_identifiers: list[str] - """Command identifiers covered by this approval.""" + display_name: str + """User-facing display name for the attachment""" - kind: PermissionDecisionApproveForLocationApprovalCommandsKind - """Approval scoped to specific command identifiers.""" + path: str + """Absolute file path""" + + type: SendAttachmentFileType + """Attachment type discriminator""" + + line_range: SendAttachmentFileLineRange | None = None + """Optional line range to scope the attachment to a specific section of the file""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalCommands': + def from_dict(obj: Any) -> 'SendAttachmentFile': assert isinstance(obj, dict) - command_identifiers = from_list(from_str, obj.get("commandIdentifiers")) - kind = PermissionDecisionApproveForLocationApprovalCommandsKind(obj.get("kind")) - return PermissionDecisionApproveForSessionApprovalCommands(command_identifiers, kind) + display_name = from_str(obj.get("displayName")) + path = from_str(obj.get("path")) + type = SendAttachmentFileType(obj.get("type")) + line_range = from_union([SendAttachmentFileLineRange.from_dict, from_none], obj.get("lineRange")) + return SendAttachmentFile(display_name, path, type, line_range) def to_dict(self) -> dict: result: dict = {} - result["commandIdentifiers"] = from_list(from_str, self.command_identifiers) - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCommandsKind, self.kind) + result["displayName"] = from_str(self.display_name) + result["path"] = from_str(self.path) + result["type"] = to_enum(SendAttachmentFileType, self.type) + if self.line_range is not None: + result["lineRange"] = from_union([lambda x: to_class(SendAttachmentFileLineRange, x), from_none], self.line_range) return result @dataclass -class PermissionDecisionApproveForLocationApprovalCustomTool: - """Schema for the `PermissionDecisionApproveForLocationApprovalCustomTool` type.""" +class SendAttachmentGithubReference: + """GitHub issue, pull request, or discussion reference""" - kind: PermissionDecisionApproveForLocationApprovalCustomToolKind - """Approval covering a custom tool.""" + number: int + """Issue, pull request, or discussion number""" - tool_name: str - """Custom tool name.""" + reference_type: SendAttachmentGithubReferenceTypeEnum + """Type of GitHub reference""" + + state: str + """Current state of the referenced item (e.g., open, closed, merged)""" + + title: str + """Title of the referenced item""" + + type: SendAttachmentGithubReferenceType + """Attachment type discriminator""" + + url: str + """URL to the referenced item on GitHub""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalCustomTool': + def from_dict(obj: Any) -> 'SendAttachmentGithubReference': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalCustomToolKind(obj.get("kind")) - tool_name = from_str(obj.get("toolName")) - return PermissionDecisionApproveForLocationApprovalCustomTool(kind, tool_name) + number = from_int(obj.get("number")) + reference_type = SendAttachmentGithubReferenceTypeEnum(obj.get("referenceType")) + state = from_str(obj.get("state")) + title = from_str(obj.get("title")) + type = SendAttachmentGithubReferenceType(obj.get("type")) + url = from_str(obj.get("url")) + return SendAttachmentGithubReference(number, reference_type, state, title, type, url) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCustomToolKind, self.kind) - result["toolName"] = from_str(self.tool_name) + result["number"] = from_int(self.number) + result["referenceType"] = to_enum(SendAttachmentGithubReferenceTypeEnum, self.reference_type) + result["state"] = from_str(self.state) + result["title"] = from_str(self.title) + result["type"] = to_enum(SendAttachmentGithubReferenceType, self.type) + result["url"] = from_str(self.url) return result @dataclass -class PermissionDecisionApproveForSessionApprovalCustomTool: - """Schema for the `PermissionDecisionApproveForSessionApprovalCustomTool` type.""" - - kind: PermissionDecisionApproveForLocationApprovalCustomToolKind - """Approval covering a custom tool.""" +class ServerSkillList: + """Skills discovered across global and project sources.""" - tool_name: str - """Custom tool name.""" + skills: list[ServerSkill] + """All discovered skills across all sources""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalCustomTool': + def from_dict(obj: Any) -> 'ServerSkillList': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalCustomToolKind(obj.get("kind")) - tool_name = from_str(obj.get("toolName")) - return PermissionDecisionApproveForSessionApprovalCustomTool(kind, tool_name) + skills = from_list(ServerSkill.from_dict, obj.get("skills")) + return ServerSkillList(skills) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalCustomToolKind, self.kind) - result["toolName"] = from_str(self.tool_name) + result["skills"] = from_list(lambda x: to_class(ServerSkill, x), self.skills) return result @dataclass -class PermissionDecisionApproveForLocationApprovalExtensionManagement: - """Schema for the `PermissionDecisionApproveForLocationApprovalExtensionManagement` type.""" +class SessionFSError: + """Describes a filesystem error.""" - kind: PermissionDecisionApproveForLocationApprovalExtensionManagementKind - """Approval covering extension lifecycle operations such as enable, disable, or reload.""" + code: SessionFSErrorCode + """Error classification""" - operation: str | None = None - """Optional operation identifier; when omitted, the approval covers all extension management - operations. - """ + message: str | None = None + """Free-form detail about the error, for logging/diagnostics""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalExtensionManagement': + def from_dict(obj: Any) -> 'SessionFSError': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalExtensionManagementKind(obj.get("kind")) - operation = from_union([from_str, from_none], obj.get("operation")) - return PermissionDecisionApproveForLocationApprovalExtensionManagement(kind, operation) + code = SessionFSErrorCode(obj.get("code")) + message = from_union([from_str, from_none], obj.get("message")) + return SessionFSError(code, message) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionManagementKind, self.kind) - if self.operation is not None: - result["operation"] = from_union([from_str, from_none], self.operation) + result["code"] = to_enum(SessionFSErrorCode, self.code) + if self.message is not None: + result["message"] = from_union([from_str, from_none], self.message) return result @dataclass -class PermissionDecisionApproveForSessionApprovalExtensionManagement: - """Schema for the `PermissionDecisionApproveForSessionApprovalExtensionManagement` type.""" +class SessionFSReaddirWithTypesEntry: + """Schema for the `SessionFsReaddirWithTypesEntry` type.""" - kind: PermissionDecisionApproveForLocationApprovalExtensionManagementKind - """Approval covering extension lifecycle operations such as enable, disable, or reload.""" + name: str + """Entry name""" - operation: str | None = None - """Optional operation identifier; when omitted, the approval covers all extension management - operations. - """ + type: SessionFSReaddirWithTypesEntryType + """Entry type""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalExtensionManagement': + def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalExtensionManagementKind(obj.get("kind")) - operation = from_union([from_str, from_none], obj.get("operation")) - return PermissionDecisionApproveForSessionApprovalExtensionManagement(kind, operation) + name = from_str(obj.get("name")) + type = SessionFSReaddirWithTypesEntryType(obj.get("type")) + return SessionFSReaddirWithTypesEntry(name, type) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionManagementKind, self.kind) - if self.operation is not None: - result["operation"] = from_union([from_str, from_none], self.operation) + result["name"] = from_str(self.name) + result["type"] = to_enum(SessionFSReaddirWithTypesEntryType, self.type) return result @dataclass -class PermissionDecisionApproveForLocationApprovalMCP: - """Schema for the `PermissionDecisionApproveForLocationApprovalMcp` type.""" +class SessionFSSetProviderRequest: + """Initial working directory, session-state path layout, and path conventions used to + register the calling SDK client as the session filesystem provider. + """ + conventions: SessionFSSetProviderConventions + """Path conventions used by this filesystem""" - kind: PermissionDecisionApproveForLocationApprovalMCPKind - """Approval covering an MCP tool.""" + initial_cwd: str + """Initial working directory for sessions""" - server_name: str - """MCP server name.""" + session_state_path: str + """Path within each session's SessionFs where the runtime stores files for that session""" - tool_name: str | None = None - """MCP tool name, or null to cover every tool on the server.""" + capabilities: SessionFSSetProviderCapabilities | None = None + """Optional capabilities declared by the provider""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMCP': + def from_dict(obj: Any) -> 'SessionFSSetProviderRequest': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMCPKind(obj.get("kind")) - server_name = from_str(obj.get("serverName")) - tool_name = from_union([from_none, from_str], obj.get("toolName")) - return PermissionDecisionApproveForLocationApprovalMCP(kind, server_name, tool_name) + conventions = SessionFSSetProviderConventions(obj.get("conventions")) + initial_cwd = from_str(obj.get("initialCwd")) + session_state_path = from_str(obj.get("sessionStatePath")) + capabilities = from_union([SessionFSSetProviderCapabilities.from_dict, from_none], obj.get("capabilities")) + return SessionFSSetProviderRequest(conventions, initial_cwd, session_state_path, capabilities) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPKind, self.kind) - result["serverName"] = from_str(self.server_name) - result["toolName"] = from_union([from_none, from_str], self.tool_name) + result["conventions"] = to_enum(SessionFSSetProviderConventions, self.conventions) + result["initialCwd"] = from_str(self.initial_cwd) + result["sessionStatePath"] = from_str(self.session_state_path) + if self.capabilities is not None: + result["capabilities"] = from_union([lambda x: to_class(SessionFSSetProviderCapabilities, x), from_none], self.capabilities) return result @dataclass -class PermissionDecisionApproveForSessionApprovalMCP: - """Schema for the `PermissionDecisionApproveForSessionApprovalMcp` type.""" - - kind: PermissionDecisionApproveForLocationApprovalMCPKind - """Approval covering an MCP tool.""" +class SessionFSSqliteQueryRequest: + """SQL query, query type, and optional bind parameters for executing a SQLite query against + the per-session database. + """ + query: str + """SQL query to execute""" - server_name: str - """MCP server name.""" + query_type: SessionFSSqliteQueryType + """How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT + (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) + """ + session_id: str + """Target session identifier""" - tool_name: str | None = None - """MCP tool name, or null to cover every tool on the server.""" + params: dict[str, float | str | None] | None = None + """Optional named bind parameters""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMCP': + def from_dict(obj: Any) -> 'SessionFSSqliteQueryRequest': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMCPKind(obj.get("kind")) - server_name = from_str(obj.get("serverName")) - tool_name = from_union([from_none, from_str], obj.get("toolName")) - return PermissionDecisionApproveForSessionApprovalMCP(kind, server_name, tool_name) + query = from_str(obj.get("query")) + query_type = SessionFSSqliteQueryType(obj.get("queryType")) + session_id = from_str(obj.get("sessionId")) + params = from_union([lambda x: from_dict(lambda x: from_union([from_none, from_float, from_str], x), x), from_none], obj.get("params")) + return SessionFSSqliteQueryRequest(query, query_type, session_id, params) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPKind, self.kind) - result["serverName"] = from_str(self.server_name) - result["toolName"] = from_union([from_none, from_str], self.tool_name) + result["query"] = from_str(self.query) + result["queryType"] = to_enum(SessionFSSqliteQueryType, self.query_type) + result["sessionId"] = from_str(self.session_id) + if self.params is not None: + result["params"] = from_union([lambda x: from_dict(lambda x: from_union([from_none, to_float, from_str], x), x), from_none], self.params) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionApproveForLocationApprovalMCPSampling: - """Schema for the `PermissionDecisionApproveForLocationApprovalMcpSampling` type.""" +class SessionsListRequest: + """Optional metadata-load limit and context filter applied to the returned sessions.""" - kind: PermissionDecisionApproveForLocationApprovalMCPSamplingKind - """Approval covering MCP sampling requests for a server.""" + filter: Filter | None = None + """Optional filter applied to the returned sessions""" - server_name: str - """MCP server name.""" + metadata_limit: int | None = None + """When provided, only the first N sessions (sorted by modification time, newest first) load + full metadata; remaining sessions return basic info only. Use 0 to return only basic info + for every session. + """ @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMCPSampling': + def from_dict(obj: Any) -> 'SessionsListRequest': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMCPSamplingKind(obj.get("kind")) - server_name = from_str(obj.get("serverName")) - return PermissionDecisionApproveForLocationApprovalMCPSampling(kind, server_name) + filter = from_union([Filter.from_dict, from_none], obj.get("filter")) + metadata_limit = from_union([from_int, from_none], obj.get("metadataLimit")) + return SessionsListRequest(filter, metadata_limit) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPSamplingKind, self.kind) - result["serverName"] = from_str(self.server_name) + if self.filter is not None: + result["filter"] = from_union([lambda x: to_class(Filter, x), from_none], self.filter) + if self.metadata_limit is not None: + result["metadataLimit"] = from_union([from_int, from_none], self.metadata_limit) return result @dataclass -class PermissionDecisionApproveForSessionApprovalMCPSampling: - """Schema for the `PermissionDecisionApproveForSessionApprovalMcpSampling` type.""" +class ShellKillRequest: + """Identifier of a process previously returned by "shell.exec" and the signal to send.""" - kind: PermissionDecisionApproveForLocationApprovalMCPSamplingKind - """Approval covering MCP sampling requests for a server.""" + process_id: str + """Process identifier returned by shell.exec""" - server_name: str - """MCP server name.""" + signal: ShellKillSignal | None = None + """Signal to send (default: SIGTERM)""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMCPSampling': + def from_dict(obj: Any) -> 'ShellKillRequest': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMCPSamplingKind(obj.get("kind")) - server_name = from_str(obj.get("serverName")) - return PermissionDecisionApproveForSessionApprovalMCPSampling(kind, server_name) + process_id = from_str(obj.get("processId")) + signal = from_union([ShellKillSignal, from_none], obj.get("signal")) + return ShellKillRequest(process_id, signal) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMCPSamplingKind, self.kind) - result["serverName"] = from_str(self.server_name) + result["processId"] = from_str(self.process_id) + if self.signal is not None: + result["signal"] = from_union([lambda x: to_enum(ShellKillSignal, x), from_none], self.signal) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionApproveForLocationApprovalMemory: - """Schema for the `PermissionDecisionApproveForLocationApprovalMemory` type.""" +class AgentInfo: + """Schema for the `AgentInfo` type. - kind: PermissionDecisionApproveForLocationApprovalMemoryKind - """Approval covering writes to long-term memory.""" + The newly selected custom agent + """ + description: str + """Description of the agent's purpose""" + + display_name: str + """Human-readable display name""" + + id: str + """Stable identifier for selection. For most agents this is the same as `name`; for + plugin/builtin agents it may differ. Always populated; defaults to `name` when no + distinct id was assigned. + """ + name: str + """Unique identifier of the custom agent""" + + mcp_servers: dict[str, Any] | None = None + """MCP server configurations attached to this agent, keyed by server name. Server config + shape mirrors the MCP `mcpServers` schema. + """ + model: str | None = None + """Preferred model id for this agent. When omitted, inherits the outer agent's model.""" + + path: str | None = None + """Absolute local file path of the agent definition. Only set for file-based agents loaded + from disk; remote agents do not have a path. + """ + skills: list[str] | None = None + """Skill names preloaded into this agent's context. Omitted means none.""" + + source: AgentInfoSource | None = None + """Where the agent definition was loaded from""" + + tools: list[str] | None = None + """Allowed tool names for this agent. Empty array means none; omitted means inherit defaults.""" + + user_invocable: bool | None = None + """Whether the agent can be selected directly by the user. Agents marked `false` are + subagent-only. + """ @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalMemory': + def from_dict(obj: Any) -> 'AgentInfo': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMemoryKind(obj.get("kind")) - return PermissionDecisionApproveForLocationApprovalMemory(kind) + description = from_str(obj.get("description")) + display_name = from_str(obj.get("displayName")) + id = from_str(obj.get("id")) + name = from_str(obj.get("name")) + mcp_servers = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("mcpServers")) + model = from_union([from_str, from_none], obj.get("model")) + path = from_union([from_str, from_none], obj.get("path")) + skills = from_union([lambda x: from_list(from_str, x), from_none], obj.get("skills")) + source = from_union([AgentInfoSource, from_none], obj.get("source")) + tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("tools")) + user_invocable = from_union([from_bool, from_none], obj.get("userInvocable")) + return AgentInfo(description, display_name, id, name, mcp_servers, model, path, skills, source, tools, user_invocable) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMemoryKind, self.kind) + result["description"] = from_str(self.description) + result["displayName"] = from_str(self.display_name) + result["id"] = from_str(self.id) + result["name"] = from_str(self.name) + if self.mcp_servers is not None: + result["mcpServers"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.mcp_servers) + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.skills is not None: + result["skills"] = from_union([lambda x: from_list(from_str, x), from_none], self.skills) + if self.source is not None: + result["source"] = from_union([lambda x: to_enum(AgentInfoSource, x), from_none], self.source) + if self.tools is not None: + result["tools"] = from_union([lambda x: from_list(from_str, x), from_none], self.tools) + if self.user_invocable is not None: + result["userInvocable"] = from_union([from_bool, from_none], self.user_invocable) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionApproveForSessionApprovalMemory: - """Schema for the `PermissionDecisionApproveForSessionApprovalMemory` type.""" +class SkillList: + """Skills available to the session, with their enabled state.""" - kind: PermissionDecisionApproveForLocationApprovalMemoryKind - """Approval covering writes to long-term memory.""" + skills: list[Skill] + """Available skills""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalMemory': + def from_dict(obj: Any) -> 'SkillList': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalMemoryKind(obj.get("kind")) - return PermissionDecisionApproveForSessionApprovalMemory(kind) + skills = from_list(Skill.from_dict, obj.get("skills")) + return SkillList(skills) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalMemoryKind, self.kind) + result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills) return result @dataclass -class PermissionDecisionApproveForLocationApprovalRead: - """Schema for the `PermissionDecisionApproveForLocationApprovalRead` type.""" +class SkillsConfigSetDisabledSkillsRequest: + """Skill names to mark as disabled in global configuration, replacing any previous list.""" - kind: PermissionDecisionApproveForLocationApprovalReadKind - """Approval covering read-only filesystem operations.""" + disabled_skills: list[str] + """List of skill names to disable""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalRead': + def from_dict(obj: Any) -> 'SkillsConfigSetDisabledSkillsRequest': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalReadKind(obj.get("kind")) - return PermissionDecisionApproveForLocationApprovalRead(kind) + disabled_skills = from_list(from_str, obj.get("disabledSkills")) + return SkillsConfigSetDisabledSkillsRequest(disabled_skills) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalReadKind, self.kind) + result["disabledSkills"] = from_list(from_str, self.disabled_skills) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionApproveForSessionApprovalRead: - """Schema for the `PermissionDecisionApproveForSessionApprovalRead` type.""" +class SkillsGetInvokedResult: + """Skills invoked during this session, ordered by invocation time (most recent last).""" - kind: PermissionDecisionApproveForLocationApprovalReadKind - """Approval covering read-only filesystem operations.""" + skills: list[SkillsInvokedSkill] + """Skills invoked during this session, ordered by invocation time (most recent last)""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalRead': + def from_dict(obj: Any) -> 'SkillsGetInvokedResult': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalReadKind(obj.get("kind")) - return PermissionDecisionApproveForSessionApprovalRead(kind) + skills = from_list(SkillsInvokedSkill.from_dict, obj.get("skills")) + return SkillsGetInvokedResult(skills) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalReadKind, self.kind) + result["skills"] = from_list(lambda x: to_class(SkillsInvokedSkill, x), self.skills) return result @dataclass -class PermissionDecisionApproveForLocationApprovalWrite: - """Schema for the `PermissionDecisionApproveForLocationApprovalWrite` type.""" +class SlashCommandAgentPromptResult: + """Schema for the `SlashCommandAgentPromptResult` type.""" - kind: PermissionDecisionApproveForLocationApprovalWriteKind - """Approval covering filesystem write operations.""" + display_prompt: str + """Prompt text to display to the user""" - @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalWrite': - assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalWriteKind(obj.get("kind")) - return PermissionDecisionApproveForLocationApprovalWrite(kind) + kind: SlashCommandAgentPromptResultKind + """Agent prompt result discriminator""" - def to_dict(self) -> dict: - result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalWriteKind, self.kind) - return result + prompt: str + """Prompt to submit to the agent""" -@dataclass -class PermissionDecisionApproveForSessionApprovalWrite: - """Schema for the `PermissionDecisionApproveForSessionApprovalWrite` type.""" + mode: SessionMode | None = None + """Optional target session mode for the agent prompt""" - kind: PermissionDecisionApproveForLocationApprovalWriteKind - """Approval covering filesystem write operations.""" + runtime_settings_changed: bool | None = None + """True when the invocation mutated user runtime settings; consumers caching settings should + refresh + """ @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalWrite': + def from_dict(obj: Any) -> 'SlashCommandAgentPromptResult': assert isinstance(obj, dict) - kind = PermissionDecisionApproveForLocationApprovalWriteKind(obj.get("kind")) - return PermissionDecisionApproveForSessionApprovalWrite(kind) + display_prompt = from_str(obj.get("displayPrompt")) + kind = SlashCommandAgentPromptResultKind(obj.get("kind")) + prompt = from_str(obj.get("prompt")) + mode = from_union([SessionMode, from_none], obj.get("mode")) + runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) + return SlashCommandAgentPromptResult(display_prompt, kind, prompt, mode, runtime_settings_changed) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalWriteKind, self.kind) + result["displayPrompt"] = from_str(self.display_prompt) + result["kind"] = to_enum(SlashCommandAgentPromptResultKind, self.kind) + result["prompt"] = from_str(self.prompt) + if self.mode is not None: + result["mode"] = from_union([lambda x: to_enum(SessionMode, x), from_none], self.mode) + if self.runtime_settings_changed is not None: + result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) return result @dataclass -class PermissionDecisionApproveOnce: - """Schema for the `PermissionDecisionApproveOnce` type.""" +class SlashCommandCompletedResult: + """Schema for the `SlashCommandCompletedResult` type.""" - kind: PermissionDecisionApproveOnceKind - """The permission request was approved for this one instance""" + kind: SlashCommandCompletedResultKind + """Completed result discriminator""" + + message: str | None = None + """Optional user-facing message describing the completed command""" + + runtime_settings_changed: bool | None = None + """True when the invocation mutated user runtime settings; consumers caching settings should + refresh + """ @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveOnce': + def from_dict(obj: Any) -> 'SlashCommandCompletedResult': assert isinstance(obj, dict) - kind = PermissionDecisionApproveOnceKind(obj.get("kind")) - return PermissionDecisionApproveOnce(kind) + kind = SlashCommandCompletedResultKind(obj.get("kind")) + message = from_union([from_str, from_none], obj.get("message")) + runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) + return SlashCommandCompletedResult(kind, message, runtime_settings_changed) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionApproveOnceKind, self.kind) + result["kind"] = to_enum(SlashCommandCompletedResultKind, self.kind) + if self.message is not None: + result["message"] = from_union([from_str, from_none], self.message) + if self.runtime_settings_changed is not None: + result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionApprovePermanently: - """Schema for the `PermissionDecisionApprovePermanently` type.""" +class TaskAgentProgress: + """Schema for the `TaskAgentProgress` type.""" - domain: str - """The URL domain to approve permanently""" + type: TaskAgentProgressType + """Progress kind""" - kind: PermissionDecisionApprovePermanentlyKind - """Approved and persisted across sessions""" + latest_intent: str | None = None + """The most recent intent reported by the agent""" + + recent_activity: list[RecentActivity] | None = None + """Recent tool execution events converted to display lines""" + + pid: int | None = None + """Process ID when available""" + + recent_output: str | None = None + """Recent stdout/stderr lines from the running shell command""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApprovePermanently': + def from_dict(obj: Any) -> 'TaskAgentProgress': assert isinstance(obj, dict) - domain = from_str(obj.get("domain")) - kind = PermissionDecisionApprovePermanentlyKind(obj.get("kind")) - return PermissionDecisionApprovePermanently(domain, kind) + type = TaskAgentProgressType(obj.get("type")) + latest_intent = from_union([from_str, from_none], obj.get("latestIntent")) + recent_activity = from_union([lambda x: from_list(RecentActivity.from_dict, x), from_none], obj.get("recentActivity")) + pid = from_union([from_int, from_none], obj.get("pid")) + recent_output = from_union([from_str, from_none], obj.get("recentOutput")) + return TaskAgentProgress(type, latest_intent, recent_activity, pid, recent_output) def to_dict(self) -> dict: result: dict = {} - result["domain"] = from_str(self.domain) - result["kind"] = to_enum(PermissionDecisionApprovePermanentlyKind, self.kind) + result["type"] = to_enum(TaskAgentProgressType, self.type) + if self.latest_intent is not None: + result["latestIntent"] = from_union([from_str, from_none], self.latest_intent) + if self.recent_activity is not None: + result["recentActivity"] = from_union([lambda x: from_list(lambda x: to_class(RecentActivity, x), x), from_none], self.recent_activity) + if self.pid is not None: + result["pid"] = from_union([from_int, from_none], self.pid) + if self.recent_output is not None: + result["recentOutput"] = from_union([from_str, from_none], self.recent_output) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionReject: - """Schema for the `PermissionDecisionReject` type.""" +class TaskProgressClass: + type: TaskAgentProgressType + """Progress kind""" - kind: PermissionDecisionRejectKind - """Denied by the user during an interactive prompt""" + latest_intent: str | None = None + """The most recent intent reported by the agent""" - feedback: str | None = None - """Optional feedback from the user explaining the denial""" + recent_activity: list[RecentActivity] | None = None + """Recent tool execution events converted to display lines""" + + pid: int | None = None + """Process ID when available""" + + recent_output: str | None = None + """Recent stdout/stderr lines from the running shell command""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionReject': + def from_dict(obj: Any) -> 'TaskProgressClass': assert isinstance(obj, dict) - kind = PermissionDecisionRejectKind(obj.get("kind")) - feedback = from_union([from_str, from_none], obj.get("feedback")) - return PermissionDecisionReject(kind, feedback) + type = TaskAgentProgressType(obj.get("type")) + latest_intent = from_union([from_str, from_none], obj.get("latestIntent")) + recent_activity = from_union([lambda x: from_list(RecentActivity.from_dict, x), from_none], obj.get("recentActivity")) + pid = from_union([from_int, from_none], obj.get("pid")) + recent_output = from_union([from_str, from_none], obj.get("recentOutput")) + return TaskProgressClass(type, latest_intent, recent_activity, pid, recent_output) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionRejectKind, self.kind) - if self.feedback is not None: - result["feedback"] = from_union([from_str, from_none], self.feedback) + result["type"] = to_enum(TaskAgentProgressType, self.type) + if self.latest_intent is not None: + result["latestIntent"] = from_union([from_str, from_none], self.latest_intent) + if self.recent_activity is not None: + result["recentActivity"] = from_union([lambda x: from_list(lambda x: to_class(RecentActivity, x), x), from_none], self.recent_activity) + if self.pid is not None: + result["pid"] = from_union([from_int, from_none], self.pid) + if self.recent_output is not None: + result["recentOutput"] = from_union([from_str, from_none], self.recent_output) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class PermissionDecisionUserNotAvailable: - """Schema for the `PermissionDecisionUserNotAvailable` type.""" +class TaskShellInfo: + """Schema for the `TaskShellInfo` type.""" - kind: PermissionDecisionUserNotAvailableKind - """Denied because user confirmation was unavailable""" + attachment_mode: TaskShellInfoAttachmentMode + """Whether the shell runs inside a managed PTY session or as an independent background + process + """ + command: str + """Command being executed""" + + description: str + """Short description of the task""" + + id: str + """Unique task identifier""" + + started_at: datetime + """ISO 8601 timestamp when the task was started""" + + status: TaskStatus + """Current lifecycle status of the task""" + + type: TaskShellInfoType + """Task kind""" + + can_promote_to_background: bool | None = None + """Whether this shell task can be promoted to background mode""" + + completed_at: datetime | None = None + """ISO 8601 timestamp when the task finished""" + + execution_mode: TaskExecutionMode | None = None + """Whether task execution is synchronously awaited or managed in the background""" + + log_path: str | None = None + """Path to the detached shell log, when available""" + + pid: int | None = None + """Process ID when available""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionUserNotAvailable': + def from_dict(obj: Any) -> 'TaskShellInfo': assert isinstance(obj, dict) - kind = PermissionDecisionUserNotAvailableKind(obj.get("kind")) - return PermissionDecisionUserNotAvailable(kind) + attachment_mode = TaskShellInfoAttachmentMode(obj.get("attachmentMode")) + command = from_str(obj.get("command")) + description = from_str(obj.get("description")) + id = from_str(obj.get("id")) + started_at = from_datetime(obj.get("startedAt")) + status = TaskStatus(obj.get("status")) + type = TaskShellInfoType(obj.get("type")) + can_promote_to_background = from_union([from_bool, from_none], obj.get("canPromoteToBackground")) + completed_at = from_union([from_datetime, from_none], obj.get("completedAt")) + execution_mode = from_union([TaskExecutionMode, from_none], obj.get("executionMode")) + log_path = from_union([from_str, from_none], obj.get("logPath")) + pid = from_union([from_int, from_none], obj.get("pid")) + return TaskShellInfo(attachment_mode, command, description, id, started_at, status, type, can_promote_to_background, completed_at, execution_mode, log_path, pid) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(PermissionDecisionUserNotAvailableKind, self.kind) + result["attachmentMode"] = to_enum(TaskShellInfoAttachmentMode, self.attachment_mode) + result["command"] = from_str(self.command) + result["description"] = from_str(self.description) + result["id"] = from_str(self.id) + result["startedAt"] = self.started_at.isoformat() + result["status"] = to_enum(TaskStatus, self.status) + result["type"] = to_enum(TaskShellInfoType, self.type) + if self.can_promote_to_background is not None: + result["canPromoteToBackground"] = from_union([from_bool, from_none], self.can_promote_to_background) + if self.completed_at is not None: + result["completedAt"] = from_union([lambda x: x.isoformat(), from_none], self.completed_at) + if self.execution_mode is not None: + result["executionMode"] = from_union([lambda x: to_enum(TaskExecutionMode, x), from_none], self.execution_mode) + if self.log_path is not None: + result["logPath"] = from_union([from_str, from_none], self.log_path) + 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 PluginList: - """Plugins installed for the session, with their enabled state and version metadata.""" +class ToolList: + """Built-in tools available for the requested model, with their parameters and instructions.""" - plugins: list[Plugin] - """Installed plugins""" + tools: list[Tool] + """List of available built-in tools with metadata""" @staticmethod - def from_dict(obj: Any) -> 'PluginList': + def from_dict(obj: Any) -> 'ToolList': assert isinstance(obj, dict) - plugins = from_list(Plugin.from_dict, obj.get("plugins")) - return PluginList(plugins) + tools = from_list(Tool.from_dict, obj.get("tools")) + return ToolList(tools) def to_dict(self) -> dict: result: dict = {} - result["plugins"] = from_list(lambda x: to_class(Plugin, x), self.plugins) + result["tools"] = from_list(lambda x: to_class(Tool, x), self.tools) return result @dataclass -class QueuedCommandResult: - """Result of the queued command execution - - Schema for the `QueuedCommandHandled` type. +class UIHandlePendingAutoModeSwitchRequest: + """Request ID of a pending `auto_mode_switch.requested` event and the user's response.""" - Schema for the `QueuedCommandNotHandled` type. - """ - handled: bool - """The command was handled + request_id: str + """The unique request ID from the auto_mode_switch.requested event""" - The command was not handled + response: UIAutoModeSwitchResponse + """User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist + as setting), or no (decline). """ - stop_processing_queue: bool | None = None - """If true, stop processing remaining queued items""" @staticmethod - def from_dict(obj: Any) -> 'QueuedCommandResult': + def from_dict(obj: Any) -> 'UIHandlePendingAutoModeSwitchRequest': assert isinstance(obj, dict) - handled = from_bool(obj.get("handled")) - stop_processing_queue = from_union([from_bool, from_none], obj.get("stopProcessingQueue")) - return QueuedCommandResult(handled, stop_processing_queue) + request_id = from_str(obj.get("requestId")) + response = UIAutoModeSwitchResponse(obj.get("response")) + return UIHandlePendingAutoModeSwitchRequest(request_id, response) def to_dict(self) -> dict: result: dict = {} - result["handled"] = from_bool(self.handled) - if self.stop_processing_queue is not None: - result["stopProcessingQueue"] = from_union([from_bool, from_none], self.stop_processing_queue) + result["requestId"] = from_str(self.request_id) + result["response"] = to_enum(UIAutoModeSwitchResponse, self.response) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class RemoteEnableRequest: - """Optional remote session mode ("off", "export", or "on"); defaults to enabling both export - and remote steering. - """ - mode: RemoteSessionMode | None = None - """Per-session remote mode. "off" disables remote, "export" exports session events to GitHub - without enabling remote steering, "on" enables both export and remote steering. - """ +class UIElicitationArrayAnyOfFieldItems: + """Schema applied to each item in the array.""" + + any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] + """Selectable options, each with a value and a display label.""" @staticmethod - def from_dict(obj: Any) -> 'RemoteEnableRequest': + def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItems': assert isinstance(obj, dict) - mode = from_union([RemoteSessionMode, from_none], obj.get("mode")) - return RemoteEnableRequest(mode) + any_of = from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, obj.get("anyOf")) + return UIElicitationArrayAnyOfFieldItems(any_of) def to_dict(self) -> dict: result: dict = {} - if self.mode is not None: - result["mode"] = from_union([lambda x: to_enum(RemoteSessionMode, x), from_none], self.mode) + result["anyOf"] = from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), self.any_of) return result @dataclass -class ServerSkillList: - """Skills discovered across global and project sources.""" +class UIElicitationArrayEnumFieldItems: + """Schema applied to each item in the array.""" - skills: list[ServerSkill] - """All discovered skills across all sources""" + enum: list[str] + """Allowed string values for each selected item.""" + + type: UIElicitationArrayEnumFieldItemsType + """Type discriminator. Always "string".""" @staticmethod - def from_dict(obj: Any) -> 'ServerSkillList': + def from_dict(obj: Any) -> 'UIElicitationArrayEnumFieldItems': assert isinstance(obj, dict) - skills = from_list(ServerSkill.from_dict, obj.get("skills")) - return ServerSkillList(skills) + enum = from_list(from_str, obj.get("enum")) + type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) + return UIElicitationArrayEnumFieldItems(enum, type) def to_dict(self) -> dict: result: dict = {} - result["skills"] = from_list(lambda x: to_class(ServerSkill, x), self.skills) + result["enum"] = from_list(from_str, self.enum) + result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) return result @dataclass -class SessionFSError: - """Describes a filesystem error.""" +class UIElicitationArrayFieldItems: + """Schema applied to each item in the array.""" - code: SessionFSErrorCode - """Error classification""" + enum: list[str] | None = None + """Allowed string values for each selected item.""" - message: str | None = None - """Free-form detail about the error, for logging/diagnostics""" + type: UIElicitationArrayEnumFieldItemsType | None = None + """Type discriminator. Always "string".""" + + any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] | None = None + """Selectable options, each with a value and a display label.""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSError': + def from_dict(obj: Any) -> 'UIElicitationArrayFieldItems': assert isinstance(obj, dict) - code = SessionFSErrorCode(obj.get("code")) - message = from_union([from_str, from_none], obj.get("message")) - return SessionFSError(code, message) + enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) + type = from_union([UIElicitationArrayEnumFieldItemsType, from_none], obj.get("type")) + any_of = from_union([lambda x: from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf")) + return UIElicitationArrayFieldItems(enum, type, any_of) def to_dict(self) -> dict: result: dict = {} - result["code"] = to_enum(SessionFSErrorCode, self.code) - if self.message is not None: - result["message"] = from_union([from_str, from_none], self.message) + if self.enum is not None: + result["enum"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum) + if self.type is not None: + result["type"] = from_union([lambda x: to_enum(UIElicitationArrayEnumFieldItemsType, x), from_none], self.type) + if self.any_of is not None: + result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of) return result @dataclass -class SessionFSReaddirWithTypesEntry: - """Schema for the `SessionFsReaddirWithTypesEntry` type.""" +class UIElicitationStringEnumField: + """Single-select string field whose allowed values are defined inline.""" - name: str - """Entry name""" + enum: list[str] + """Allowed string values.""" - type: SessionFSReaddirWithTypesEntryType - """Entry type""" + type: UIElicitationArrayEnumFieldItemsType + """Type discriminator. Always "string".""" + + default: str | None = None + """Default value selected when the form is first shown.""" + + description: str | None = None + """Help text describing the field.""" + + enum_names: list[str] | None = None + """Optional display labels for each enum value, in the same order as `enum`.""" + + title: str | None = None + """Human-readable label for the field.""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry': + def from_dict(obj: Any) -> 'UIElicitationStringEnumField': assert isinstance(obj, dict) - name = from_str(obj.get("name")) - type = SessionFSReaddirWithTypesEntryType(obj.get("type")) - return SessionFSReaddirWithTypesEntry(name, type) + enum = from_list(from_str, obj.get("enum")) + type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) + default = from_union([from_str, from_none], obj.get("default")) + description = from_union([from_str, from_none], obj.get("description")) + 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")) + return UIElicitationStringEnumField(enum, type, default, description, enum_names, title) def to_dict(self) -> dict: result: dict = {} - result["name"] = from_str(self.name) - result["type"] = to_enum(SessionFSReaddirWithTypesEntryType, self.type) + result["enum"] = from_list(from_str, self.enum) + result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) + if self.default is not None: + result["default"] = from_union([from_str, from_none], self.default) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.enum_names is not None: + result["enumNames"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum_names) + if self.title is not None: + result["title"] = from_union([from_str, from_none], self.title) return result @dataclass -class SessionFSSetProviderRequest: - """Initial working directory, session-state path layout, and path conventions used to - register the calling SDK client as the session filesystem provider. - """ - conventions: SessionFSSetProviderConventions - """Path conventions used by this filesystem""" +class UIElicitationSchemaPropertyString: + """Free-text string field with optional length and format constraints.""" - initial_cwd: str - """Initial working directory for sessions""" + type: UIElicitationArrayEnumFieldItemsType + """Type discriminator. Always "string".""" - session_state_path: str - """Path within each session's SessionFs where the runtime stores files for that session""" + default: str | None = None + """Default value populated in the input when the form is first shown.""" - capabilities: SessionFSSetProviderCapabilities | None = None - """Optional capabilities declared by the provider""" + description: str | None = None + """Help text describing the field.""" + + format: UIElicitationSchemaPropertyStringFormat | None = None + """Optional format hint that constrains the accepted input.""" + + max_length: int | None = None + """Maximum number of characters allowed.""" + + min_length: int | None = None + """Minimum number of characters required.""" + + title: str | None = None + """Human-readable label for the field.""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSSetProviderRequest': + def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyString': assert isinstance(obj, dict) - conventions = SessionFSSetProviderConventions(obj.get("conventions")) - initial_cwd = from_str(obj.get("initialCwd")) - session_state_path = from_str(obj.get("sessionStatePath")) - capabilities = from_union([SessionFSSetProviderCapabilities.from_dict, from_none], obj.get("capabilities")) - return SessionFSSetProviderRequest(conventions, initial_cwd, session_state_path, capabilities) + type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) + default = from_union([from_str, from_none], obj.get("default")) + description = from_union([from_str, from_none], obj.get("description")) + format = from_union([UIElicitationSchemaPropertyStringFormat, from_none], obj.get("format")) + max_length = from_union([from_int, from_none], obj.get("maxLength")) + min_length = from_union([from_int, from_none], obj.get("minLength")) + title = from_union([from_str, from_none], obj.get("title")) + return UIElicitationSchemaPropertyString(type, default, description, format, max_length, min_length, title) def to_dict(self) -> dict: result: dict = {} - result["conventions"] = to_enum(SessionFSSetProviderConventions, self.conventions) - result["initialCwd"] = from_str(self.initial_cwd) - result["sessionStatePath"] = from_str(self.session_state_path) - if self.capabilities is not None: - result["capabilities"] = from_union([lambda x: to_class(SessionFSSetProviderCapabilities, x), from_none], self.capabilities) + result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) + if self.default is not None: + result["default"] = from_union([from_str, from_none], self.default) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.format is not None: + 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([from_int, from_none], self.max_length) + if self.min_length is not None: + result["minLength"] = from_union([from_int, from_none], self.min_length) + if self.title is not None: + result["title"] = from_union([from_str, from_none], self.title) return result @dataclass -class SessionFSSqliteQueryRequest: - """SQL query, query type, and optional bind parameters for executing a SQLite query against - the per-session database. - """ - query: str - """SQL query to execute""" +class UIElicitationStringOneOfField: + """Single-select string field where each option pairs a value with a display label.""" - query_type: SessionFSSqliteQueryType - """How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT - (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) - """ - session_id: str - """Target session identifier""" + one_of: list[UIElicitationStringOneOfFieldOneOf] + """Selectable options, each with a value and a display label.""" - params: dict[str, float | str | None] | None = None - """Optional named bind parameters""" + type: UIElicitationArrayEnumFieldItemsType + """Type discriminator. Always "string".""" + + default: str | None = None + """Default value selected when the form is first shown.""" + + description: str | None = None + """Help text describing the field.""" + + title: str | None = None + """Human-readable label for the field.""" @staticmethod - def from_dict(obj: Any) -> 'SessionFSSqliteQueryRequest': + def from_dict(obj: Any) -> 'UIElicitationStringOneOfField': assert isinstance(obj, dict) - query = from_str(obj.get("query")) - query_type = SessionFSSqliteQueryType(obj.get("queryType")) - session_id = from_str(obj.get("sessionId")) - params = from_union([lambda x: from_dict(lambda x: from_union([from_none, from_float, from_str], x), x), from_none], obj.get("params")) - return SessionFSSqliteQueryRequest(query, query_type, session_id, params) + one_of = from_list(UIElicitationStringOneOfFieldOneOf.from_dict, obj.get("oneOf")) + type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) + default = from_union([from_str, from_none], obj.get("default")) + description = from_union([from_str, from_none], obj.get("description")) + title = from_union([from_str, from_none], obj.get("title")) + return UIElicitationStringOneOfField(one_of, type, default, description, title) def to_dict(self) -> dict: result: dict = {} - result["query"] = from_str(self.query) - result["queryType"] = to_enum(SessionFSSqliteQueryType, self.query_type) - result["sessionId"] = from_str(self.session_id) - if self.params is not None: - result["params"] = from_union([lambda x: from_dict(lambda x: from_union([from_none, to_float, from_str], x), x), from_none], self.params) + result["oneOf"] = from_list(lambda x: to_class(UIElicitationStringOneOfFieldOneOf, x), self.one_of) + result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) + if self.default is not None: + result["default"] = from_union([from_str, from_none], self.default) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.title is not None: + result["title"] = from_union([from_str, from_none], self.title) return result @dataclass -class ShellKillRequest: - """Identifier of a process previously returned by "shell.exec" and the signal to send.""" +class UIElicitationResponse: + """The elicitation response (accept with form values, decline, or cancel)""" - process_id: str - """Process identifier returned by shell.exec""" + action: UIElicitationResponseAction + """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" - signal: ShellKillSignal | None = None - """Signal to send (default: SIGTERM)""" + 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) -> 'ShellKillRequest': + def from_dict(obj: Any) -> 'UIElicitationResponse': assert isinstance(obj, dict) - process_id = from_str(obj.get("processId")) - signal = from_union([ShellKillSignal, from_none], obj.get("signal")) - return ShellKillRequest(process_id, signal) + action = UIElicitationResponseAction(obj.get("action")) + content = from_union([lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) + return UIElicitationResponse(action, content) def to_dict(self) -> dict: result: dict = {} - result["processId"] = from_str(self.process_id) - if self.signal is not None: - result["signal"] = from_union([lambda x: to_enum(ShellKillSignal, x), from_none], self.signal) + result["action"] = to_enum(UIElicitationResponseAction, self.action) + if self.content is not None: + result["content"] = from_union([lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SkillList: - """Skills available to the session, with their enabled state.""" +class UIElicitationSchemaPropertyBoolean: + """Boolean field rendered as a yes/no toggle.""" - skills: list[Skill] - """Available skills""" + type: UIElicitationSchemaPropertyBooleanType + """Type discriminator. Always "boolean".""" + + default: bool | None = None + """Default value selected when the form is first shown.""" + + description: str | None = None + """Help text describing the field.""" + + title: str | None = None + """Human-readable label for the field.""" @staticmethod - def from_dict(obj: Any) -> 'SkillList': + def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyBoolean': assert isinstance(obj, dict) - skills = from_list(Skill.from_dict, obj.get("skills")) - return SkillList(skills) + type = UIElicitationSchemaPropertyBooleanType(obj.get("type")) + default = from_union([from_bool, from_none], obj.get("default")) + description = from_union([from_str, from_none], obj.get("description")) + title = from_union([from_str, from_none], obj.get("title")) + return UIElicitationSchemaPropertyBoolean(type, default, description, title) def to_dict(self) -> dict: result: dict = {} - result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills) + result["type"] = to_enum(UIElicitationSchemaPropertyBooleanType, self.type) + if self.default is not None: + result["default"] = from_union([from_bool, from_none], self.default) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.title is not None: + result["title"] = from_union([from_str, from_none], self.title) return result @dataclass -class SkillsConfigSetDisabledSkillsRequest: - """Skill names to mark as disabled in global configuration, replacing any previous list.""" +class UIElicitationSchemaPropertyNumber: + """Numeric field accepting either a number or an integer.""" - disabled_skills: list[str] - """List of skill names to disable""" + type: UIElicitationSchemaPropertyNumberType + """Numeric type accepted by the field.""" + + default: float | None = None + """Default value populated in the input when the form is first shown.""" + + description: str | None = None + """Help text describing the field.""" + + maximum: float | None = None + """Maximum allowed value (inclusive).""" + + minimum: float | None = None + """Minimum allowed value (inclusive).""" + + title: str | None = None + """Human-readable label for the field.""" @staticmethod - def from_dict(obj: Any) -> 'SkillsConfigSetDisabledSkillsRequest': + def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyNumber': assert isinstance(obj, dict) - disabled_skills = from_list(from_str, obj.get("disabledSkills")) - return SkillsConfigSetDisabledSkillsRequest(disabled_skills) + type = UIElicitationSchemaPropertyNumberType(obj.get("type")) + default = from_union([from_float, from_none], obj.get("default")) + description = from_union([from_str, from_none], obj.get("description")) + maximum = from_union([from_float, from_none], obj.get("maximum")) + minimum = from_union([from_float, from_none], obj.get("minimum")) + title = from_union([from_str, from_none], obj.get("title")) + return UIElicitationSchemaPropertyNumber(type, default, description, maximum, minimum, title) def to_dict(self) -> dict: result: dict = {} - result["disabledSkills"] = from_list(from_str, self.disabled_skills) + result["type"] = to_enum(UIElicitationSchemaPropertyNumberType, self.type) + if self.default is not None: + result["default"] = from_union([to_float, from_none], self.default) + if self.description is not None: + result["description"] = from_union([from_str, from_none], self.description) + if self.maximum is not None: + result["maximum"] = from_union([to_float, from_none], self.maximum) + if self.minimum is not None: + result["minimum"] = from_union([to_float, from_none], self.minimum) + if self.title is not None: + result["title"] = from_union([from_str, from_none], self.title) return result @dataclass -class SlashCommandAgentPromptResult: - """Schema for the `SlashCommandAgentPromptResult` type.""" - - display_prompt: str - """Prompt text to display to the user""" +class UIExitPlanModeResponse: + """Schema for the `UIExitPlanModeResponse` type.""" - kind: SlashCommandAgentPromptResultKind - """Agent prompt result discriminator""" + approved: bool + """Whether the plan was approved.""" - prompt: str - """Prompt to submit to the agent""" + auto_approve_edits: bool | None = None + """Whether subsequent edits should be auto-approved without confirmation.""" - mode: SessionMode | None = None - """Optional target session mode for the agent prompt""" + feedback: str | None = None + """Feedback from the user when they declined the plan or requested changes.""" - runtime_settings_changed: bool | None = None - """True when the invocation mutated user runtime settings; consumers caching settings should - refresh + selected_action: UIExitPlanModeAction | None = None + """The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, + otherwise 'interactive'. """ @staticmethod - def from_dict(obj: Any) -> 'SlashCommandAgentPromptResult': + def from_dict(obj: Any) -> 'UIExitPlanModeResponse': assert isinstance(obj, dict) - display_prompt = from_str(obj.get("displayPrompt")) - kind = SlashCommandAgentPromptResultKind(obj.get("kind")) - prompt = from_str(obj.get("prompt")) - mode = from_union([SessionMode, from_none], obj.get("mode")) - runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) - return SlashCommandAgentPromptResult(display_prompt, kind, prompt, mode, runtime_settings_changed) + approved = from_bool(obj.get("approved")) + 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([UIExitPlanModeAction, from_none], obj.get("selectedAction")) + return UIExitPlanModeResponse(approved, auto_approve_edits, feedback, selected_action) def to_dict(self) -> dict: result: dict = {} - result["displayPrompt"] = from_str(self.display_prompt) - result["kind"] = to_enum(SlashCommandAgentPromptResultKind, self.kind) - result["prompt"] = from_str(self.prompt) - if self.mode is not None: - result["mode"] = from_union([lambda x: to_enum(SessionMode, x), from_none], self.mode) - if self.runtime_settings_changed is not None: - result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) + result["approved"] = from_bool(self.approved) + if self.auto_approve_edits is not None: + result["autoApproveEdits"] = from_union([from_bool, from_none], self.auto_approve_edits) + if self.feedback is not None: + result["feedback"] = from_union([from_str, from_none], self.feedback) + if self.selected_action is not None: + result["selectedAction"] = from_union([lambda x: to_enum(UIExitPlanModeAction, x), from_none], self.selected_action) return result @dataclass -class SlashCommandCompletedResult: - """Schema for the `SlashCommandCompletedResult` type.""" - - kind: SlashCommandCompletedResultKind - """Completed result discriminator""" +class UIHandlePendingUserInputRequest: + """Request ID of a pending `user_input.requested` event and the user's response.""" - message: str | None = None - """Optional user-facing message describing the completed command""" + request_id: str + """The unique request ID from the user_input.requested event""" - runtime_settings_changed: bool | None = None - """True when the invocation mutated user runtime settings; consumers caching settings should - refresh - """ + response: UIUserInputResponse + """Schema for the `UIUserInputResponse` type.""" @staticmethod - def from_dict(obj: Any) -> 'SlashCommandCompletedResult': + def from_dict(obj: Any) -> 'UIHandlePendingUserInputRequest': assert isinstance(obj, dict) - kind = SlashCommandCompletedResultKind(obj.get("kind")) - message = from_union([from_str, from_none], obj.get("message")) - runtime_settings_changed = from_union([from_bool, from_none], obj.get("runtimeSettingsChanged")) - return SlashCommandCompletedResult(kind, message, runtime_settings_changed) + request_id = from_str(obj.get("requestId")) + response = UIUserInputResponse.from_dict(obj.get("response")) + return UIHandlePendingUserInputRequest(request_id, response) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(SlashCommandCompletedResultKind, self.kind) - if self.message is not None: - result["message"] = from_union([from_str, from_none], self.message) - if self.runtime_settings_changed is not None: - result["runtimeSettingsChanged"] = from_union([from_bool, from_none], self.runtime_settings_changed) + result["requestId"] = from_str(self.request_id) + result["response"] = to_class(UIUserInputResponse, self.response) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class TaskShellInfo: - """Schema for the `TaskShellInfo` type.""" - - attachment_mode: TaskShellInfoAttachmentMode - """Whether the shell runs inside a managed PTY session or as an independent background - process - """ - command: str - """Command being executed""" - - description: str - """Short description of the task""" - - id: str - """Unique task identifier""" - - started_at: datetime - """ISO 8601 timestamp when the task was started""" - - status: TaskStatus - """Current lifecycle status of the task""" - - type: TaskShellInfoType - """Task kind""" - - can_promote_to_background: bool | None = None - """Whether this shell task can be promoted to background mode""" +class UsageMetricsModelMetric: + """Schema for the `UsageMetricsModelMetric` type.""" - completed_at: datetime | None = None - """ISO 8601 timestamp when the task finished""" + requests: UsageMetricsModelMetricRequests + """Request count and cost metrics for this model""" - execution_mode: TaskExecutionMode | None = None - """Whether task execution is synchronously awaited or managed in the background""" + usage: UsageMetricsModelMetricUsage + """Token usage metrics for this model""" - log_path: str | None = None - """Path to the detached shell log, when available""" + token_details: dict[str, UsageMetricsModelMetricTokenDetail] | None = None + """Token count details per type""" - pid: int | None = None - """Process ID when available""" + total_nano_aiu: int | None = None + """Accumulated nano-AI units cost for this model""" @staticmethod - def from_dict(obj: Any) -> 'TaskShellInfo': + def from_dict(obj: Any) -> 'UsageMetricsModelMetric': assert isinstance(obj, dict) - attachment_mode = TaskShellInfoAttachmentMode(obj.get("attachmentMode")) - command = from_str(obj.get("command")) - description = from_str(obj.get("description")) - id = from_str(obj.get("id")) - started_at = from_datetime(obj.get("startedAt")) - status = TaskStatus(obj.get("status")) - type = TaskShellInfoType(obj.get("type")) - can_promote_to_background = from_union([from_bool, from_none], obj.get("canPromoteToBackground")) - completed_at = from_union([from_datetime, from_none], obj.get("completedAt")) - execution_mode = from_union([TaskExecutionMode, from_none], obj.get("executionMode")) - log_path = from_union([from_str, from_none], obj.get("logPath")) - pid = from_union([from_int, from_none], obj.get("pid")) - return TaskShellInfo(attachment_mode, command, description, id, started_at, status, type, can_promote_to_background, completed_at, execution_mode, log_path, pid) + requests = UsageMetricsModelMetricRequests.from_dict(obj.get("requests")) + usage = UsageMetricsModelMetricUsage.from_dict(obj.get("usage")) + token_details = from_union([lambda x: from_dict(UsageMetricsModelMetricTokenDetail.from_dict, x), from_none], obj.get("tokenDetails")) + total_nano_aiu = from_union([from_int, from_none], obj.get("totalNanoAiu")) + return UsageMetricsModelMetric(requests, usage, token_details, total_nano_aiu) def to_dict(self) -> dict: result: dict = {} - result["attachmentMode"] = to_enum(TaskShellInfoAttachmentMode, self.attachment_mode) - result["command"] = from_str(self.command) - result["description"] = from_str(self.description) - result["id"] = from_str(self.id) - result["startedAt"] = self.started_at.isoformat() - result["status"] = to_enum(TaskStatus, self.status) - result["type"] = to_enum(TaskShellInfoType, self.type) - if self.can_promote_to_background is not None: - result["canPromoteToBackground"] = from_union([from_bool, from_none], self.can_promote_to_background) - if self.completed_at is not None: - result["completedAt"] = from_union([lambda x: x.isoformat(), from_none], self.completed_at) - if self.execution_mode is not None: - result["executionMode"] = from_union([lambda x: to_enum(TaskExecutionMode, x), from_none], self.execution_mode) - if self.log_path is not None: - result["logPath"] = from_union([from_str, from_none], self.log_path) - if self.pid is not None: - result["pid"] = from_union([from_int, from_none], self.pid) + result["requests"] = to_class(UsageMetricsModelMetricRequests, self.requests) + result["usage"] = to_class(UsageMetricsModelMetricUsage, self.usage) + if self.token_details is not None: + result["tokenDetails"] = from_union([lambda x: from_dict(lambda x: to_class(UsageMetricsModelMetricTokenDetail, x), x), from_none], self.token_details) + if self.total_nano_aiu is not None: + result["totalNanoAiu"] = from_union([from_int, from_none], self.total_nano_aiu) return result @dataclass -class ToolList: - """Built-in tools available for the requested model, with their parameters and instructions.""" +class WorkspacesSaveLargePasteResult: + """Descriptor for the saved paste file, or null when the workspace is unavailable.""" - tools: list[Tool] - """List of available built-in tools with metadata""" + saved: Saved | None = None + """Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, + non-infinite sessions, remote sessions) + """ @staticmethod - def from_dict(obj: Any) -> 'ToolList': + def from_dict(obj: Any) -> 'WorkspacesSaveLargePasteResult': assert isinstance(obj, dict) - tools = from_list(Tool.from_dict, obj.get("tools")) - return ToolList(tools) + saved = from_union([Saved.from_dict, from_none], obj.get("saved")) + return WorkspacesSaveLargePasteResult(saved) def to_dict(self) -> dict: result: dict = {} - result["tools"] = from_list(lambda x: to_class(Tool, x), self.tools) + result["saved"] = from_union([lambda x: to_class(Saved, x), from_none], self.saved) return result @dataclass -class UIElicitationArrayAnyOfFieldItems: - """Schema applied to each item in the array.""" +class SlashCommandInfo: + """Schema for the `SlashCommandInfo` type.""" - any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] - """Selectable options, each with a value and a display label.""" + allow_during_agent_execution: bool + """Whether the command may run while an agent turn is active""" + + description: str + """Human-readable command description""" + + kind: SlashCommandKind + """Coarse command category for grouping and behavior: runtime built-in, skill-backed + command, or SDK/client-owned command + """ + name: str + """Canonical command name without a leading slash""" + + aliases: list[str] | None = None + """Canonical aliases without leading slashes""" + + experimental: bool | None = None + """Whether the command is experimental""" + + input: SlashCommandInput | None = None + """Optional unstructured input hint""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItems': + def from_dict(obj: Any) -> 'SlashCommandInfo': assert isinstance(obj, dict) - any_of = from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, obj.get("anyOf")) - return UIElicitationArrayAnyOfFieldItems(any_of) + allow_during_agent_execution = from_bool(obj.get("allowDuringAgentExecution")) + description = from_str(obj.get("description")) + kind = SlashCommandKind(obj.get("kind")) + name = from_str(obj.get("name")) + aliases = from_union([lambda x: from_list(from_str, x), from_none], obj.get("aliases")) + experimental = from_union([from_bool, from_none], obj.get("experimental")) + input = from_union([SlashCommandInput.from_dict, from_none], obj.get("input")) + return SlashCommandInfo(allow_during_agent_execution, description, kind, name, aliases, experimental, input) def to_dict(self) -> dict: result: dict = {} - result["anyOf"] = from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), self.any_of) + result["allowDuringAgentExecution"] = from_bool(self.allow_during_agent_execution) + result["description"] = from_str(self.description) + result["kind"] = to_enum(SlashCommandKind, self.kind) + result["name"] = from_str(self.name) + if self.aliases is not None: + result["aliases"] = from_union([lambda x: from_list(from_str, x), from_none], self.aliases) + if self.experimental is not None: + result["experimental"] = from_union([from_bool, from_none], self.experimental) + if self.input is not None: + result["input"] = from_union([lambda x: to_class(SlashCommandInput, x), from_none], self.input) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UIElicitationArrayEnumFieldItems: - """Schema applied to each item in the array.""" +class RemoteSessionConnectionResult: + """Remote session connection result.""" - enum: list[str] - """Allowed string values for each selected item.""" + metadata: ConnectedRemoteSessionMetadata + """Metadata for a connected remote session.""" - type: UIElicitationArrayEnumFieldItemsType - """Type discriminator. Always "string".""" + session_id: str + """SDK session ID for the connected remote session.""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationArrayEnumFieldItems': + def from_dict(obj: Any) -> 'RemoteSessionConnectionResult': assert isinstance(obj, dict) - enum = from_list(from_str, obj.get("enum")) - type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) - return UIElicitationArrayEnumFieldItems(enum, type) + metadata = ConnectedRemoteSessionMetadata.from_dict(obj.get("metadata")) + session_id = from_str(obj.get("sessionId")) + return RemoteSessionConnectionResult(metadata, session_id) def to_dict(self) -> dict: result: dict = {} - result["enum"] = from_list(from_str, self.enum) - result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) + result["metadata"] = to_class(ConnectedRemoteSessionMetadata, self.metadata) + result["sessionId"] = from_str(self.session_id) return result @dataclass -class UIElicitationArrayFieldItems: - """Schema applied to each item in the array.""" - - enum: list[str] | None = None - """Allowed string values for each selected item.""" +class CopilotUserResponse: + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ + access_type_sku: str | None = None + analytics_tracking_id: str | None = None + assigned_date: Any = None + can_signup_for_limited: bool | None = None + chat_enabled: bool | None = None + cli_remote_control_enabled: bool | None = None + cloud_session_storage_enabled: bool | None = None + codex_agent_enabled: bool | None = None + copilot_plan: str | None = None + copilotignore_enabled: bool | None = None + endpoints: CopilotUserResponseEndpoints | None = None + """Schema for the `CopilotUserResponseEndpoints` type.""" - type: UIElicitationArrayEnumFieldItemsType | None = None - """Type discriminator. Always "string".""" + is_mcp_enabled: Any = None + limited_user_quotas: dict[str, float] | None = None + limited_user_reset_date: str | None = None + login: str | None = None + monthly_quotas: dict[str, float] | None = None + organization_list: Any = None + organization_login_list: list[str] | None = None + quota_reset_date: str | None = None + quota_reset_date_utc: str | None = None + quota_snapshots: dict[str, CopilotUserResponseQuotaSnapshots | None] | None = None + """Schema for the `CopilotUserResponseQuotaSnapshots` type.""" - any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] | None = None - """Selectable options, each with a value and a display label.""" + restricted_telemetry: bool | None = None + token_based_billing: bool | None = None @staticmethod - def from_dict(obj: Any) -> 'UIElicitationArrayFieldItems': + def from_dict(obj: Any) -> 'CopilotUserResponse': assert isinstance(obj, dict) - enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum")) - type = from_union([UIElicitationArrayEnumFieldItemsType, from_none], obj.get("type")) - any_of = from_union([lambda x: from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf")) - return UIElicitationArrayFieldItems(enum, type, any_of) + access_type_sku = from_union([from_str, from_none], obj.get("access_type_sku")) + analytics_tracking_id = from_union([from_str, from_none], obj.get("analytics_tracking_id")) + assigned_date = obj.get("assigned_date") + can_signup_for_limited = from_union([from_bool, from_none], obj.get("can_signup_for_limited")) + chat_enabled = from_union([from_bool, from_none], obj.get("chat_enabled")) + cli_remote_control_enabled = from_union([from_bool, from_none], obj.get("cli_remote_control_enabled")) + cloud_session_storage_enabled = from_union([from_bool, from_none], obj.get("cloud_session_storage_enabled")) + codex_agent_enabled = from_union([from_bool, from_none], obj.get("codex_agent_enabled")) + copilot_plan = from_union([from_str, from_none], obj.get("copilot_plan")) + copilotignore_enabled = from_union([from_bool, from_none], obj.get("copilotignore_enabled")) + endpoints = from_union([CopilotUserResponseEndpoints.from_dict, from_none], obj.get("endpoints")) + is_mcp_enabled = obj.get("is_mcp_enabled") + limited_user_quotas = from_union([lambda x: from_dict(from_float, x), from_none], obj.get("limited_user_quotas")) + limited_user_reset_date = from_union([from_str, from_none], obj.get("limited_user_reset_date")) + login = from_union([from_str, from_none], obj.get("login")) + monthly_quotas = from_union([lambda x: from_dict(from_float, x), from_none], obj.get("monthly_quotas")) + organization_list = obj.get("organization_list") + organization_login_list = from_union([lambda x: from_list(from_str, x), from_none], obj.get("organization_login_list")) + quota_reset_date = from_union([from_str, from_none], obj.get("quota_reset_date")) + quota_reset_date_utc = from_union([from_str, from_none], obj.get("quota_reset_date_utc")) + quota_snapshots = from_union([lambda x: from_dict(lambda x: from_union([CopilotUserResponseQuotaSnapshots.from_dict, from_none], x), x), from_none], obj.get("quota_snapshots")) + restricted_telemetry = from_union([from_bool, from_none], obj.get("restricted_telemetry")) + token_based_billing = from_union([from_bool, from_none], obj.get("token_based_billing")) + return CopilotUserResponse(access_type_sku, analytics_tracking_id, assigned_date, can_signup_for_limited, chat_enabled, cli_remote_control_enabled, cloud_session_storage_enabled, codex_agent_enabled, copilot_plan, copilotignore_enabled, endpoints, is_mcp_enabled, limited_user_quotas, limited_user_reset_date, login, monthly_quotas, organization_list, organization_login_list, quota_reset_date, quota_reset_date_utc, quota_snapshots, restricted_telemetry, token_based_billing) def to_dict(self) -> dict: result: dict = {} - if self.enum is not None: - result["enum"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum) - if self.type is not None: - result["type"] = from_union([lambda x: to_enum(UIElicitationArrayEnumFieldItemsType, x), from_none], self.type) - if self.any_of is not None: - result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of) + if self.access_type_sku is not None: + result["access_type_sku"] = from_union([from_str, from_none], self.access_type_sku) + if self.analytics_tracking_id is not None: + result["analytics_tracking_id"] = from_union([from_str, from_none], self.analytics_tracking_id) + if self.assigned_date is not None: + result["assigned_date"] = self.assigned_date + if self.can_signup_for_limited is not None: + result["can_signup_for_limited"] = from_union([from_bool, from_none], self.can_signup_for_limited) + if self.chat_enabled is not None: + result["chat_enabled"] = from_union([from_bool, from_none], self.chat_enabled) + if self.cli_remote_control_enabled is not None: + result["cli_remote_control_enabled"] = from_union([from_bool, from_none], self.cli_remote_control_enabled) + if self.cloud_session_storage_enabled is not None: + result["cloud_session_storage_enabled"] = from_union([from_bool, from_none], self.cloud_session_storage_enabled) + if self.codex_agent_enabled is not None: + result["codex_agent_enabled"] = from_union([from_bool, from_none], self.codex_agent_enabled) + if self.copilot_plan is not None: + result["copilot_plan"] = from_union([from_str, from_none], self.copilot_plan) + if self.copilotignore_enabled is not None: + result["copilotignore_enabled"] = from_union([from_bool, from_none], self.copilotignore_enabled) + if self.endpoints is not None: + result["endpoints"] = from_union([lambda x: to_class(CopilotUserResponseEndpoints, x), from_none], self.endpoints) + if self.is_mcp_enabled is not None: + result["is_mcp_enabled"] = self.is_mcp_enabled + if self.limited_user_quotas is not None: + result["limited_user_quotas"] = from_union([lambda x: from_dict(to_float, x), from_none], self.limited_user_quotas) + if self.limited_user_reset_date is not None: + result["limited_user_reset_date"] = from_union([from_str, from_none], self.limited_user_reset_date) + if self.login is not None: + result["login"] = from_union([from_str, from_none], self.login) + if self.monthly_quotas is not None: + result["monthly_quotas"] = from_union([lambda x: from_dict(to_float, x), from_none], self.monthly_quotas) + if self.organization_list is not None: + result["organization_list"] = self.organization_list + if self.organization_login_list is not None: + result["organization_login_list"] = from_union([lambda x: from_list(from_str, x), from_none], self.organization_login_list) + if self.quota_reset_date is not None: + result["quota_reset_date"] = from_union([from_str, from_none], self.quota_reset_date) + if self.quota_reset_date_utc is not None: + result["quota_reset_date_utc"] = from_union([from_str, from_none], self.quota_reset_date_utc) + if self.quota_snapshots is not None: + result["quota_snapshots"] = from_union([lambda x: from_dict(lambda x: from_union([lambda x: to_class(CopilotUserResponseQuotaSnapshots, x), from_none], x), x), from_none], self.quota_snapshots) + if self.restricted_telemetry is not None: + result["restricted_telemetry"] = from_union([from_bool, from_none], self.restricted_telemetry) + if self.token_based_billing is not None: + result["token_based_billing"] = from_union([from_bool, from_none], self.token_based_billing) return result @dataclass -class UIElicitationStringEnumField: - """Single-select string field whose allowed values are defined inline.""" - - enum: list[str] - """Allowed string values.""" +class MCPDiscoverResult: + """MCP servers discovered from user, workspace, plugin, and built-in sources.""" - type: UIElicitationArrayEnumFieldItemsType - """Type discriminator. Always "string".""" + servers: list[DiscoveredMCPServer] + """MCP servers discovered from all sources""" - default: str | None = None - """Default value selected when the form is first shown.""" + @staticmethod + def from_dict(obj: Any) -> 'MCPDiscoverResult': + assert isinstance(obj, dict) + servers = from_list(DiscoveredMCPServer.from_dict, obj.get("servers")) + return MCPDiscoverResult(servers) - description: str | None = None - """Help text describing the field.""" + def to_dict(self) -> dict: + result: dict = {} + result["servers"] = from_list(lambda x: to_class(DiscoveredMCPServer, x), self.servers) + return result - enum_names: list[str] | None = None - """Optional display labels for each enum value, in the same order as `enum`.""" +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class ExtensionList: + """Extensions discovered for the session, with their current status.""" - title: str | None = None - """Human-readable label for the field.""" + extensions: list[Extension] + """Discovered extensions and their current status""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationStringEnumField': + def from_dict(obj: Any) -> 'ExtensionList': assert isinstance(obj, dict) - enum = from_list(from_str, obj.get("enum")) - type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) - default = from_union([from_str, from_none], obj.get("default")) - description = from_union([from_str, from_none], obj.get("description")) - 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")) - return UIElicitationStringEnumField(enum, type, default, description, enum_names, title) + extensions = from_list(Extension.from_dict, obj.get("extensions")) + return ExtensionList(extensions) def to_dict(self) -> dict: result: dict = {} - result["enum"] = from_list(from_str, self.enum) - result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) - if self.default is not None: - result["default"] = from_union([from_str, from_none], self.default) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) - if self.enum_names is not None: - result["enumNames"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum_names) - if self.title is not None: - result["title"] = from_union([from_str, from_none], self.title) + result["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions) return result @dataclass -class UIElicitationSchemaPropertyString: - """Free-text string field with optional length and format constraints.""" - - type: UIElicitationArrayEnumFieldItemsType - """Type discriminator. Always "string".""" - - default: str | None = None - """Default value populated in the input when the form is first shown.""" +class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess: + """Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` + type. + """ + extension_name: str + """Extension name.""" - description: str | None = None - """Help text describing the field.""" + kind: PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind + """Approval covering an extension's request to access a permission-gated capability.""" - format: UIElicitationSchemaPropertyStringFormat | None = None - """Optional format hint that constrains the accepted input.""" + @staticmethod + def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess': + assert isinstance(obj, dict) + extension_name = from_str(obj.get("extensionName")) + kind = PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind(obj.get("kind")) + return PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess(extension_name, kind) - max_length: float | None = None - """Maximum number of characters allowed.""" + def to_dict(self) -> dict: + result: dict = {} + result["extensionName"] = from_str(self.extension_name) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind, self.kind) + return result - min_length: float | None = None - """Minimum number of characters required.""" +@dataclass +class PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess: + """Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` + type. + """ + extension_name: str + """Extension name.""" - title: str | None = None - """Human-readable label for the field.""" + kind: PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind + """Approval covering an extension's request to access a permission-gated capability.""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyString': + def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess': assert isinstance(obj, dict) - type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) - default = from_union([from_str, from_none], obj.get("default")) - description = from_union([from_str, from_none], obj.get("description")) - 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")) - title = from_union([from_str, from_none], obj.get("title")) - return UIElicitationSchemaPropertyString(type, default, description, format, max_length, min_length, title) + extension_name = from_str(obj.get("extensionName")) + kind = PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind(obj.get("kind")) + return PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess(extension_name, kind) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) - if self.default is not None: - result["default"] = from_union([from_str, from_none], self.default) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) - if self.format is not None: - 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: - result["minLength"] = from_union([to_float, from_none], self.min_length) - if self.title is not None: - result["title"] = from_union([from_str, from_none], self.title) + result["extensionName"] = from_str(self.extension_name) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind, self.kind) return result @dataclass -class UIElicitationStringOneOfField: - """Single-select string field where each option pairs a value with a display label.""" - - one_of: list[UIElicitationStringOneOfFieldOneOf] - """Selectable options, each with a value and a display label.""" - - type: UIElicitationArrayEnumFieldItemsType - """Type discriminator. Always "string".""" - - default: str | None = None - """Default value selected when the form is first shown.""" +class UserToolSessionApprovalExtensionManagement: + """Schema for the `UserToolSessionApprovalExtensionManagement` type.""" - description: str | None = None - """Help text describing the field.""" + kind: PermissionDecisionApproveForLocationApprovalExtensionManagementKind + """Extension management approval kind""" - title: str | None = None - """Human-readable label for the field.""" + operation: str | None = None + """Optional operation identifier""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationStringOneOfField': + def from_dict(obj: Any) -> 'UserToolSessionApprovalExtensionManagement': assert isinstance(obj, dict) - one_of = from_list(UIElicitationStringOneOfFieldOneOf.from_dict, obj.get("oneOf")) - type = UIElicitationArrayEnumFieldItemsType(obj.get("type")) - default = from_union([from_str, from_none], obj.get("default")) - description = from_union([from_str, from_none], obj.get("description")) - title = from_union([from_str, from_none], obj.get("title")) - return UIElicitationStringOneOfField(one_of, type, default, description, title) + kind = PermissionDecisionApproveForLocationApprovalExtensionManagementKind(obj.get("kind")) + operation = from_union([from_str, from_none], obj.get("operation")) + return UserToolSessionApprovalExtensionManagement(kind, operation) def to_dict(self) -> dict: result: dict = {} - result["oneOf"] = from_list(lambda x: to_class(UIElicitationStringOneOfFieldOneOf, x), self.one_of) - result["type"] = to_enum(UIElicitationArrayEnumFieldItemsType, self.type) - if self.default is not None: - result["default"] = from_union([from_str, from_none], self.default) - if self.description is not None: - result["description"] = from_union([from_str, from_none], self.description) - if self.title is not None: - result["title"] = from_union([from_str, from_none], self.title) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionManagementKind, self.kind) + if self.operation is not None: + result["operation"] = from_union([from_str, from_none], self.operation) return result @dataclass -class UIElicitationResponse: - """The elicitation response (accept with form values, decline, or cancel)""" +class UserToolSessionApprovalExtensionPermissionAccess: + """Schema for the `UserToolSessionApprovalExtensionPermissionAccess` type.""" - action: UIElicitationResponseAction - """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)""" + extension_name: str + """Extension name""" - content: dict[str, float | bool | list[str] | str] | None = None - """The form values submitted by the user (present when action is 'accept')""" + kind: PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind + """Extension permission access approval kind""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationResponse': + def from_dict(obj: Any) -> 'UserToolSessionApprovalExtensionPermissionAccess': assert isinstance(obj, dict) - action = UIElicitationResponseAction(obj.get("action")) - content = from_union([lambda x: from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], obj.get("content")) - return UIElicitationResponse(action, content) + extension_name = from_str(obj.get("extensionName")) + kind = PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind(obj.get("kind")) + return UserToolSessionApprovalExtensionPermissionAccess(extension_name, kind) def to_dict(self) -> dict: result: dict = {} - result["action"] = to_enum(UIElicitationResponseAction, self.action) - if self.content is not None: - result["content"] = from_union([lambda x: from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x), from_none], self.content) + result["extensionName"] = from_str(self.extension_name) + result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind, self.kind) return result @dataclass -class UIElicitationSchemaPropertyBoolean: - """Boolean field rendered as a yes/no toggle.""" +class ExternalToolTextResultForLlmContent: + """A content block within a tool result, which may be text, terminal output, image, audio, + or a resource - type: UIElicitationSchemaPropertyBooleanType - """Type discriminator. Always "boolean".""" + Plain text content block - default: bool | None = None - """Default value selected when the form is first shown.""" + Terminal/shell output content block with optional exit code and working directory + + Image content block with base64-encoded data + + Audio content block with base64-encoded data + + Resource link content block referencing an external resource + + Embedded resource content block with inline text or binary data + """ + type: ExternalToolTextResultForLlmContentType + """Content block type discriminator""" + + text: str | None = None + """The text content + + Terminal/shell output text + """ + cwd: str | None = None + """Working directory where the command was executed""" + + exit_code: int | None = None + """Process exit code, if the command has completed""" + + data: str | None = None + """Base64-encoded image data + + Base64-encoded audio data + """ + mime_type: str | None = None + """MIME type of the image (e.g., image/png, image/jpeg) + + MIME type of the audio (e.g., audio/wav, audio/mpeg) + MIME type of the resource content + """ description: str | None = None - """Help text describing the field.""" + """Human-readable description of the resource""" + + icons: list[ExternalToolTextResultForLlmContentResourceLinkIcon] | None = None + """Icons associated with this resource""" + + name: str | None = None + """Resource name identifier""" + + size: int | None = None + """Size of the resource in bytes""" title: str | None = None - """Human-readable label for the field.""" + """Human-readable display title for the resource""" + + uri: str | None = None + """URI identifying the resource""" + + resource: ExternalToolTextResultForLlmContentResourceDetails | None = None + """The embedded resource contents, either text or base64-encoded binary""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyBoolean': + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContent': assert isinstance(obj, dict) - type = UIElicitationSchemaPropertyBooleanType(obj.get("type")) - default = from_union([from_bool, from_none], obj.get("default")) + type = ExternalToolTextResultForLlmContentType(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_int, 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(ExternalToolTextResultForLlmContentResourceLinkIcon.from_dict, x), from_none], obj.get("icons")) + name = from_union([from_str, from_none], obj.get("name")) + size = from_union([from_int, from_none], obj.get("size")) title = from_union([from_str, from_none], obj.get("title")) - return UIElicitationSchemaPropertyBoolean(type, default, description, title) + uri = from_union([from_str, from_none], obj.get("uri")) + resource = from_union([(lambda x: from_union([EmbeddedTextResourceContents.from_dict, EmbeddedBlobResourceContents.from_dict], x)), from_none], obj.get("resource")) + return ExternalToolTextResultForLlmContent(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(UIElicitationSchemaPropertyBooleanType, self.type) - if self.default is not None: - result["default"] = from_union([from_bool, from_none], self.default) + result["type"] = to_enum(ExternalToolTextResultForLlmContentType, self.type) + if self.text is not None: + result["text"] = from_union([from_str, from_none], self.text) + if self.cwd is not None: + result["cwd"] = from_union([from_str, from_none], self.cwd) + if self.exit_code is not None: + result["exitCode"] = from_union([from_int, from_none], self.exit_code) + if self.data is not None: + result["data"] = from_union([from_str, from_none], self.data) + if self.mime_type is not None: + result["mimeType"] = from_union([from_str, from_none], self.mime_type) 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(ExternalToolTextResultForLlmContentResourceLinkIcon, 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: + result["size"] = from_union([from_int, from_none], self.size) if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) + 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: from_union([lambda x: to_class(EmbeddedTextResourceContents, x), lambda x: to_class(EmbeddedBlobResourceContents, x)], x), from_none], self.resource) return result @dataclass -class UIElicitationSchemaPropertyNumber: - """Numeric field accepting either a number or an integer.""" +class ExternalToolTextResultForLlmContentResourceLink: + """Resource link content block referencing an external resource""" - type: UIElicitationSchemaPropertyNumberType - """Numeric type accepted by the field.""" + name: str + """Resource name identifier""" - default: float | None = None - """Default value populated in the input when the form is first shown.""" + type: ExternalToolTextResultForLlmContentResourceLinkType + """Content block type discriminator""" + + uri: str + """URI identifying the resource""" description: str | None = None - """Help text describing the field.""" + """Human-readable description of the resource""" - maximum: float | None = None - """Maximum allowed value (inclusive).""" + icons: list[ExternalToolTextResultForLlmContentResourceLinkIcon] | None = None + """Icons associated with this resource""" - minimum: float | None = None - """Minimum allowed value (inclusive).""" + mime_type: str | None = None + """MIME type of the resource content""" + + size: int | None = None + """Size of the resource in bytes""" title: str | None = None - """Human-readable label for the field.""" + """Human-readable display title for the resource""" @staticmethod - def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyNumber': + def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContentResourceLink': assert isinstance(obj, dict) - type = UIElicitationSchemaPropertyNumberType(obj.get("type")) - default = from_union([from_float, from_none], obj.get("default")) + name = from_str(obj.get("name")) + type = ExternalToolTextResultForLlmContentResourceLinkType(obj.get("type")) + uri = from_str(obj.get("uri")) description = from_union([from_str, from_none], obj.get("description")) - maximum = from_union([from_float, from_none], obj.get("maximum")) - minimum = from_union([from_float, from_none], obj.get("minimum")) + icons = from_union([lambda x: from_list(ExternalToolTextResultForLlmContentResourceLinkIcon.from_dict, x), from_none], obj.get("icons")) + mime_type = from_union([from_str, from_none], obj.get("mimeType")) + size = from_union([from_int, from_none], obj.get("size")) title = from_union([from_str, from_none], obj.get("title")) - return UIElicitationSchemaPropertyNumber(type, default, description, maximum, minimum, title) + return ExternalToolTextResultForLlmContentResourceLink(name, type, uri, description, icons, mime_type, size, title) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(UIElicitationSchemaPropertyNumberType, self.type) - if self.default is not None: - result["default"] = from_union([to_float, from_none], self.default) + result["name"] = from_str(self.name) + result["type"] = to_enum(ExternalToolTextResultForLlmContentResourceLinkType, self.type) + result["uri"] = from_str(self.uri) if self.description is not None: result["description"] = from_union([from_str, from_none], self.description) - if self.maximum is not None: - result["maximum"] = from_union([to_float, from_none], self.maximum) - if self.minimum is not None: - result["minimum"] = from_union([to_float, from_none], self.minimum) + if self.icons is not None: + result["icons"] = from_union([lambda x: from_list(lambda x: to_class(ExternalToolTextResultForLlmContentResourceLinkIcon, x), x), from_none], self.icons) + if self.mime_type is not None: + result["mimeType"] = from_union([from_str, from_none], self.mime_type) + if self.size is not None: + result["size"] = from_union([from_int, from_none], self.size) if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) return result # Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class UsageMetricsModelMetric: - """Schema for the `UsageMetricsModelMetric` type.""" - - requests: UsageMetricsModelMetricRequests - """Request count and cost metrics for this model""" - - usage: UsageMetricsModelMetricUsage - """Token usage metrics for this model""" - - token_details: dict[str, UsageMetricsModelMetricTokenDetail] | None = None - """Token count details per type""" +class InstalledPluginSource: + """Schema for the `InstalledPluginSourceGithub` type. - total_nano_aiu: int | None = None - """Accumulated nano-AI units cost for this model""" + Schema for the `InstalledPluginSourceUrl` type. - @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")) - token_details = from_union([lambda x: from_dict(UsageMetricsModelMetricTokenDetail.from_dict, x), from_none], obj.get("tokenDetails")) - total_nano_aiu = from_union([from_int, from_none], obj.get("totalNanoAiu")) - return UsageMetricsModelMetric(requests, usage, token_details, total_nano_aiu) + Schema for the `InstalledPluginSourceLocal` type. + """ + source: PurpleSource + """Constant value. Always "github". - def to_dict(self) -> dict: - result: dict = {} - result["requests"] = to_class(UsageMetricsModelMetricRequests, self.requests) - result["usage"] = to_class(UsageMetricsModelMetricUsage, self.usage) - if self.token_details is not None: - result["tokenDetails"] = from_union([lambda x: from_dict(lambda x: to_class(UsageMetricsModelMetricTokenDetail, x), x), from_none], self.token_details) - if self.total_nano_aiu is not None: - result["totalNanoAiu"] = from_union([from_int, from_none], self.total_nano_aiu) - return result + Constant value. Always "url". -@dataclass -class Workspace: - id: UUID - branch: str | None = None - chronicle_sync_dismissed: bool | None = None - created_at: datetime | None = None - cwd: str | None = None - git_root: str | None = None - host_type: HostType | None = None - mc_last_event_id: str | None = None - mc_session_id: str | None = None - mc_task_id: str | None = None - name: str | None = None - remote_steerable: bool | None = None - repository: str | None = None - summary_count: int | None = None - updated_at: datetime | None = None - user_named: bool | None = None + Constant value. Always "local". + """ + path: str | None = None + ref: str | None = None + repo: str | None = None + url: str | None = None @staticmethod - def from_dict(obj: Any) -> 'Workspace': + def from_dict(obj: Any) -> 'InstalledPluginSource': assert isinstance(obj, dict) - id = UUID(obj.get("id")) - branch = from_union([from_str, from_none], obj.get("branch")) - chronicle_sync_dismissed = from_union([from_bool, from_none], obj.get("chronicle_sync_dismissed")) - created_at = from_union([from_datetime, from_none], obj.get("created_at")) - cwd = from_union([from_str, from_none], obj.get("cwd")) - git_root = from_union([from_str, from_none], obj.get("git_root")) - host_type = from_union([HostType, from_none], obj.get("host_type")) - mc_last_event_id = from_union([from_str, from_none], obj.get("mc_last_event_id")) - mc_session_id = from_union([from_str, from_none], obj.get("mc_session_id")) - mc_task_id = from_union([from_str, from_none], obj.get("mc_task_id")) - name = from_union([from_str, from_none], obj.get("name")) - remote_steerable = from_union([from_bool, from_none], obj.get("remote_steerable")) - repository = from_union([from_str, from_none], obj.get("repository")) - summary_count = from_union([from_int, from_none], obj.get("summary_count")) - updated_at = from_union([from_datetime, from_none], obj.get("updated_at")) - user_named = from_union([from_bool, from_none], obj.get("user_named")) - return Workspace(id, branch, chronicle_sync_dismissed, created_at, cwd, git_root, host_type, mc_last_event_id, mc_session_id, mc_task_id, name, remote_steerable, repository, summary_count, updated_at, user_named) + source = PurpleSource(obj.get("source")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + repo = from_union([from_str, from_none], obj.get("repo")) + url = from_union([from_str, from_none], obj.get("url")) + return InstalledPluginSource(source, path, ref, repo, url) def to_dict(self) -> dict: result: dict = {} - result["id"] = str(self.id) - if self.branch is not None: - result["branch"] = from_union([from_str, from_none], self.branch) - if self.chronicle_sync_dismissed is not None: - result["chronicle_sync_dismissed"] = from_union([from_bool, from_none], self.chronicle_sync_dismissed) - if self.created_at is not None: - result["created_at"] = from_union([lambda x: x.isoformat(), from_none], self.created_at) - if self.cwd is not None: - result["cwd"] = from_union([from_str, from_none], self.cwd) - if self.git_root is not None: - result["git_root"] = from_union([from_str, from_none], self.git_root) - if self.host_type is not None: - result["host_type"] = from_union([lambda x: to_enum(HostType, x), from_none], self.host_type) - if self.mc_last_event_id is not None: - result["mc_last_event_id"] = from_union([from_str, from_none], self.mc_last_event_id) - if self.mc_session_id is not None: - result["mc_session_id"] = from_union([from_str, from_none], self.mc_session_id) - if self.mc_task_id is not None: - result["mc_task_id"] = from_union([from_str, from_none], self.mc_task_id) - if self.name is not None: - result["name"] = from_union([from_str, from_none], self.name) - if self.remote_steerable is not None: - result["remote_steerable"] = from_union([from_bool, from_none], self.remote_steerable) - if self.repository is not None: - result["repository"] = from_union([from_str, from_none], self.repository) - if self.summary_count is not None: - result["summary_count"] = from_union([from_int, from_none], self.summary_count) - if self.updated_at is not None: - result["updated_at"] = from_union([lambda x: x.isoformat(), from_none], self.updated_at) - if self.user_named is not None: - result["user_named"] = from_union([from_bool, from_none], self.user_named) + result["source"] = to_enum(PurpleSource, self.source) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + if self.repo is not None: + result["repo"] = from_union([from_str, from_none], self.repo) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class SlashCommandInfo: - """Schema for the `SlashCommandInfo` type.""" - - allow_during_agent_execution: bool - """Whether the command may run while an agent turn is active""" +class SessionInstalledPluginSource: + """Schema for the `SessionInstalledPluginSourceGithub` type. - description: str - """Human-readable command description""" + Schema for the `SessionInstalledPluginSourceUrl` type. - kind: SlashCommandKind - """Coarse command category for grouping and behavior: runtime built-in, skill-backed - command, or SDK/client-owned command + Schema for the `SessionInstalledPluginSourceLocal` type. """ - name: str - """Canonical command name without a leading slash""" - - aliases: list[str] | None = None - """Canonical aliases without leading slashes""" + source: PurpleSource + """Constant value. Always "github". - experimental: bool | None = None - """Whether the command is experimental""" + Constant value. Always "url". - input: SlashCommandInput | None = None - """Optional unstructured input hint""" + Constant value. Always "local". + """ + path: str | None = None + ref: str | None = None + repo: str | None = None + url: str | None = None @staticmethod - def from_dict(obj: Any) -> 'SlashCommandInfo': + def from_dict(obj: Any) -> 'SessionInstalledPluginSource': assert isinstance(obj, dict) - allow_during_agent_execution = from_bool(obj.get("allowDuringAgentExecution")) - description = from_str(obj.get("description")) - kind = SlashCommandKind(obj.get("kind")) - name = from_str(obj.get("name")) - aliases = from_union([lambda x: from_list(from_str, x), from_none], obj.get("aliases")) - experimental = from_union([from_bool, from_none], obj.get("experimental")) - input = from_union([SlashCommandInput.from_dict, from_none], obj.get("input")) - return SlashCommandInfo(allow_during_agent_execution, description, kind, name, aliases, experimental, input) + source = PurpleSource(obj.get("source")) + path = from_union([from_str, from_none], obj.get("path")) + ref = from_union([from_str, from_none], obj.get("ref")) + repo = from_union([from_str, from_none], obj.get("repo")) + url = from_union([from_str, from_none], obj.get("url")) + return SessionInstalledPluginSource(source, path, ref, repo, url) def to_dict(self) -> dict: result: dict = {} - result["allowDuringAgentExecution"] = from_bool(self.allow_during_agent_execution) - result["description"] = from_str(self.description) - result["kind"] = to_enum(SlashCommandKind, self.kind) - result["name"] = from_str(self.name) - if self.aliases is not None: - result["aliases"] = from_union([lambda x: from_list(from_str, x), from_none], self.aliases) - if self.experimental is not None: - result["experimental"] = from_union([from_bool, from_none], self.experimental) - if self.input is not None: - result["input"] = from_union([lambda x: to_class(SlashCommandInput, x), from_none], self.input) + result["source"] = to_enum(PurpleSource, self.source) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.ref is not None: + result["ref"] = from_union([from_str, from_none], self.ref) + if self.repo is not None: + result["repo"] = from_union([from_str, from_none], self.repo) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) return result -# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class RemoteSessionConnectionResult: - """Remote session connection result.""" - - metadata: ConnectedRemoteSessionMetadata - """Metadata for a connected remote session.""" +class InstructionsGetSourcesResult: + """Instruction sources loaded for the session, in merge order.""" - session_id: str - """SDK session ID for the connected remote session.""" + sources: list[InstructionsSources] + """Instruction sources for the session""" @staticmethod - def from_dict(obj: Any) -> 'RemoteSessionConnectionResult': + def from_dict(obj: Any) -> 'InstructionsGetSourcesResult': assert isinstance(obj, dict) - metadata = ConnectedRemoteSessionMetadata.from_dict(obj.get("metadata")) - session_id = from_str(obj.get("sessionId")) - return RemoteSessionConnectionResult(metadata, session_id) + sources = from_list(InstructionsSources.from_dict, obj.get("sources")) + return InstructionsGetSourcesResult(sources) def to_dict(self) -> dict: result: dict = {} - result["metadata"] = to_class(ConnectedRemoteSessionMetadata, self.metadata) - result["sessionId"] = from_str(self.session_id) + result["sources"] = from_list(lambda x: to_class(InstructionsSources, x), self.sources) return result @dataclass -class MCPDiscoverResult: - """MCP servers discovered from user, workspace, plugin, and built-in sources.""" +class MCPConfigAddRequest: + """MCP server name and configuration to add to user configuration.""" - servers: list[DiscoveredMCPServer] - """MCP servers discovered from all sources""" + config: MCPServerConfig + """MCP server configuration (stdio process or remote HTTP/SSE)""" + + name: str + """Unique name for the MCP server""" @staticmethod - def from_dict(obj: Any) -> 'MCPDiscoverResult': + def from_dict(obj: Any) -> 'MCPConfigAddRequest': assert isinstance(obj, dict) - servers = from_list(DiscoveredMCPServer.from_dict, obj.get("servers")) - return MCPDiscoverResult(servers) + config = MCPServerConfig.from_dict(obj.get("config")) + name = from_str(obj.get("name")) + return MCPConfigAddRequest(config, name) def to_dict(self) -> dict: result: dict = {} - result["servers"] = from_list(lambda x: to_class(DiscoveredMCPServer, x), self.servers) + result["config"] = to_class(MCPServerConfig, self.config) + 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 ExtensionList: - """Extensions discovered for the session, with their current status.""" +class MCPConfigList: + """User-configured MCP servers, keyed by server name.""" - extensions: list[Extension] - """Discovered extensions and their current status""" + servers: dict[str, MCPServerConfig] + """All MCP servers from user config, keyed by name""" @staticmethod - def from_dict(obj: Any) -> 'ExtensionList': + def from_dict(obj: Any) -> 'MCPConfigList': assert isinstance(obj, dict) - extensions = from_list(Extension.from_dict, obj.get("extensions")) - return ExtensionList(extensions) + servers = from_dict(MCPServerConfig.from_dict, obj.get("servers")) + return MCPConfigList(servers) def to_dict(self) -> dict: result: dict = {} - result["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions) + result["servers"] = from_dict(lambda x: to_class(MCPServerConfig, x), self.servers) return result @dataclass -class PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess: - """Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` - type. - """ - extension_name: str - """Extension name.""" +class MCPConfigUpdateRequest: + """MCP server name and replacement configuration to write to user configuration.""" - kind: PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind - """Approval covering an extension's request to access a permission-gated capability.""" + config: MCPServerConfig + """MCP server configuration (stdio process or remote HTTP/SSE)""" + + name: str + """Name of the MCP server to update""" @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess': + def from_dict(obj: Any) -> 'MCPConfigUpdateRequest': assert isinstance(obj, dict) - extension_name = from_str(obj.get("extensionName")) - kind = PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind(obj.get("kind")) - return PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess(extension_name, kind) + config = MCPServerConfig.from_dict(obj.get("config")) + name = from_str(obj.get("name")) + return MCPConfigUpdateRequest(config, name) def to_dict(self) -> dict: result: dict = {} - result["extensionName"] = from_str(self.extension_name) - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind, self.kind) + result["config"] = to_class(MCPServerConfig, self.config) + 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 PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess: - """Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` - type. - """ - extension_name: str - """Extension name.""" +class MetadataRecordContextChangeRequest: + """Updated working-directory/git context to record on the session.""" - kind: PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind - """Approval covering an extension's request to access a permission-gated capability.""" + context: SessionWorkingDirectoryContext + """Updated working directory and git context. Emitted as the new payload of + `session.context_changed`. + """ @staticmethod - def from_dict(obj: Any) -> 'PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess': + def from_dict(obj: Any) -> 'MetadataRecordContextChangeRequest': assert isinstance(obj, dict) - extension_name = from_str(obj.get("extensionName")) - kind = PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind(obj.get("kind")) - return PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess(extension_name, kind) + context = SessionWorkingDirectoryContext.from_dict(obj.get("context")) + return MetadataRecordContextChangeRequest(context) def to_dict(self) -> dict: result: dict = {} - result["extensionName"] = from_str(self.extension_name) - result["kind"] = to_enum(PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKind, self.kind) + result["context"] = to_class(SessionWorkingDirectoryContext, self.context) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class ExternalToolTextResultForLlmContent: - """A content block within a tool result, which may be text, terminal output, image, audio, - or a resource +class SessionMetadata: + """Schema for the `SessionMetadata` type.""" - Plain text content block + is_remote: bool + """True for remote (GitHub) sessions; false for local""" - Terminal/shell output content block with optional exit code and working directory + modified_time: str + """Last-modified time of the session's persisted state, as ISO 8601""" - Image content block with base64-encoded data + session_id: str + """Stable session identifier""" - Audio content block with base64-encoded data + start_time: str + """Session creation time as an ISO 8601 timestamp""" - Resource link content block referencing an external resource + context: SessionContext | None = None + """Schema for the `SessionContext` type.""" - Embedded resource content block with inline text or binary data + mc_task_id: str | None = None + """GitHub task ID, when this local session is bound to one. Only present for local sessions + exported to remote control. """ - type: ExternalToolTextResultForLlmContentType - """Content block type discriminator""" + name: str | None = None + """Optional human-friendly name set via /rename""" - text: str | None = None - """The text content + summary: str | None = None + """Short summary of the session, when one has been derived""" - Terminal/shell output text + @staticmethod + def from_dict(obj: Any) -> 'SessionMetadata': + assert isinstance(obj, dict) + is_remote = from_bool(obj.get("isRemote")) + modified_time = from_str(obj.get("modifiedTime")) + session_id = from_str(obj.get("sessionId")) + start_time = from_str(obj.get("startTime")) + context = from_union([SessionContext.from_dict, from_none], obj.get("context")) + mc_task_id = from_union([from_str, from_none], obj.get("mcTaskId")) + name = from_union([from_str, from_none], obj.get("name")) + summary = from_union([from_str, from_none], obj.get("summary")) + return SessionMetadata(is_remote, modified_time, session_id, start_time, context, mc_task_id, name, summary) + + def to_dict(self) -> dict: + result: dict = {} + result["isRemote"] = from_bool(self.is_remote) + result["modifiedTime"] = from_str(self.modified_time) + result["sessionId"] = from_str(self.session_id) + result["startTime"] = from_str(self.start_time) + if self.context is not None: + result["context"] = from_union([lambda x: to_class(SessionContext, x), from_none], self.context) + if self.mc_task_id is not None: + result["mcTaskId"] = from_union([from_str, from_none], self.mc_task_id) + if self.name is not None: + result["name"] = from_union([from_str, from_none], self.name) + if self.summary is not None: + result["summary"] = from_union([from_str, from_none], self.summary) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsGetLastForContextRequest: + """Optional working-directory context used to score session relevance.""" + + context: SessionContext | None = None + """Optional working-directory context used to score session relevance. When omitted the + most-recently-modified session wins. """ - cwd: str | None = None - """Working directory where the command was executed""" - exit_code: float | None = None - """Process exit code, if the command has completed""" + @staticmethod + def from_dict(obj: Any) -> 'SessionsGetLastForContextRequest': + assert isinstance(obj, dict) + context = from_union([SessionContext.from_dict, from_none], obj.get("context")) + return SessionsGetLastForContextRequest(context) - data: str | None = None - """Base64-encoded image data + def to_dict(self) -> dict: + result: dict = {} + if self.context is not None: + result["context"] = from_union([lambda x: to_class(SessionContext, x), from_none], self.context) + return result - Base64-encoded audio data +@dataclass +class PermissionPathsConfig: + """If specified, replaces the session's path-permission policy. The runtime constructs the + appropriate PathManager based on these inputs (rooted at the session's working + directory). Omit to leave the current path policy unchanged. + """ + additional_directories: list[str] | None = None + """Additional directories to allow tool access to (in addition to the session's working + directory). When `unrestricted` is true, these are still pre-populated on the + UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention + completion). + """ + include_temp_directory: bool | None = None + """Whether to include the system temp directory in the allowed list (defaults to true). + Ignored when `unrestricted` is true. + """ + unrestricted: bool | None = None + """If true, the runtime allows access to all paths without prompting. Equivalent to + constructing an UnrestrictedPathManager. + """ + workspace_path: str | None = None + """Workspace root path (special-cased to be allowed even before the directory exists). + Ignored when `unrestricted` is true. """ - mime_type: str | None = None - """MIME type of the image (e.g., image/png, image/jpeg) - MIME type of the audio (e.g., audio/wav, audio/mpeg) + @staticmethod + def from_dict(obj: Any) -> 'PermissionPathsConfig': + assert isinstance(obj, dict) + additional_directories = from_union([lambda x: from_list(from_str, x), from_none], obj.get("additionalDirectories")) + include_temp_directory = from_union([from_bool, from_none], obj.get("includeTempDirectory")) + unrestricted = from_union([from_bool, from_none], obj.get("unrestricted")) + workspace_path = from_union([from_str, from_none], obj.get("workspacePath")) + return PermissionPathsConfig(additional_directories, include_temp_directory, unrestricted, workspace_path) + + def to_dict(self) -> dict: + result: dict = {} + if self.additional_directories is not None: + result["additionalDirectories"] = from_union([lambda x: from_list(from_str, x), from_none], self.additional_directories) + if self.include_temp_directory is not None: + result["includeTempDirectory"] = from_union([from_bool, from_none], self.include_temp_directory) + if self.unrestricted is not None: + result["unrestricted"] = from_union([from_bool, from_none], self.unrestricted) + if self.workspace_path is not None: + result["workspacePath"] = from_union([from_str, from_none], self.workspace_path) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class WorkspaceSummary: + """Public-facing projection of workspace metadata for SDK / TUI consumers""" + + id: UUID + """Workspace identifier (1:1 with sessionId)""" + + branch: str | None = None + """Branch checked out at session start, if any""" - MIME type of the resource content - """ - description: str | None = None - """Human-readable description of the resource""" + created_at: datetime | None = None + """ISO 8601 timestamp when the workspace was created""" - icons: list[ExternalToolTextResultForLlmContentResourceLinkIcon] | None = None - """Icons associated with this resource""" + cwd: str | None = None + """Current working directory at session start""" - name: str | None = None - """Resource name identifier""" + git_root: str | None = None + """Resolved git root for cwd, if any""" - size: float | None = None - """Size of the resource in bytes""" + host_type: SessionContextHostType | None = None + """Repository host type, if known""" - title: str | None = None - """Human-readable display title for the resource""" + name: str | None = None + """Display name for the session, if set""" - uri: str | None = None - """URI identifying the resource""" + repository: str | None = None + """Repository identifier in 'owner/repo' or 'org/project/repo' format, if any""" - resource: ExternalToolTextResultForLlmContentResourceDetails | None = None - """The embedded resource contents, either text or base64-encoded binary""" + updated_at: datetime | None = None + """ISO 8601 timestamp when the workspace was last updated""" @staticmethod - def from_dict(obj: Any) -> 'ExternalToolTextResultForLlmContent': + def from_dict(obj: Any) -> 'WorkspaceSummary': assert isinstance(obj, dict) - type = ExternalToolTextResultForLlmContentType(obj.get("type")) - text = from_union([from_str, from_none], obj.get("text")) + id = UUID(obj.get("id")) + branch = from_union([from_str, from_none], obj.get("branch")) + created_at = from_union([from_datetime, from_none], obj.get("created_at")) 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(ExternalToolTextResultForLlmContentResourceLinkIcon.from_dict, x), from_none], obj.get("icons")) + git_root = from_union([from_str, from_none], obj.get("git_root")) + host_type = from_union([SessionContextHostType, from_none], obj.get("host_type")) 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([(lambda x: from_union([EmbeddedTextResourceContents.from_dict, EmbeddedBlobResourceContents.from_dict], x)), from_none], obj.get("resource")) - return ExternalToolTextResultForLlmContent(type, text, cwd, exit_code, data, mime_type, description, icons, name, size, title, uri, resource) + repository = from_union([from_str, from_none], obj.get("repository")) + updated_at = from_union([from_datetime, from_none], obj.get("updated_at")) + return WorkspaceSummary(id, branch, created_at, cwd, git_root, host_type, name, repository, updated_at) def to_dict(self) -> dict: result: dict = {} - result["type"] = to_enum(ExternalToolTextResultForLlmContentType, self.type) - if self.text is not None: - result["text"] = from_union([from_str, from_none], self.text) + result["id"] = str(self.id) + if self.branch is not None: + result["branch"] = from_union([from_str, from_none], self.branch) + if self.created_at is not None: + result["created_at"] = from_union([lambda x: x.isoformat(), from_none], self.created_at) if self.cwd is not None: result["cwd"] = from_union([from_str, from_none], self.cwd) - if self.exit_code is not None: - result["exitCode"] = from_union([to_float, from_none], self.exit_code) - if self.data is not None: - result["data"] = from_union([from_str, from_none], self.data) - if self.mime_type is not None: - result["mimeType"] = from_union([from_str, from_none], self.mime_type) - 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(ExternalToolTextResultForLlmContentResourceLinkIcon, x), x), from_none], self.icons) + if self.git_root is not None: + result["git_root"] = from_union([from_str, from_none], self.git_root) + if self.host_type is not None: + result["host_type"] = from_union([lambda x: to_enum(SessionContextHostType, x), from_none], self.host_type) if self.name is not None: result["name"] = from_union([from_str, from_none], self.name) - if self.size is not None: - result["size"] = from_union([to_float, from_none], self.size) - if self.title is not None: - result["title"] = from_union([from_str, from_none], self.title) - 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: from_union([lambda x: to_class(EmbeddedTextResourceContents, x), lambda x: to_class(EmbeddedBlobResourceContents, x)], x), from_none], self.resource) + if self.repository is not None: + result["repository"] = from_union([from_str, from_none], self.repository) + if self.updated_at is not None: + result["updated_at"] = from_union([lambda x: x.isoformat(), from_none], self.updated_at) return result @dataclass -class ExternalToolTextResultForLlmContentResourceLink: - """Resource link content block referencing an external resource""" +class WorkspacesGetWorkspaceResult: + """Current workspace metadata for the session, including its absolute filesystem path when + available. + """ + path: str | None = None + """Absolute filesystem path to the workspace directory. Omitted when the session has no + workspace (e.g. remote sessions). + """ + workspace: Workspace | None = None + """Current workspace metadata, or null if not available""" - name: str - """Resource name identifier""" + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesGetWorkspaceResult': + assert isinstance(obj, dict) + path = from_union([from_str, from_none], obj.get("path")) + workspace = from_union([Workspace.from_dict, from_none], obj.get("workspace")) + return WorkspacesGetWorkspaceResult(path, workspace) - type: ExternalToolTextResultForLlmContentResourceLinkType - """Content block type discriminator""" + def to_dict(self) -> dict: + result: dict = {} + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + result["workspace"] = from_union([lambda x: to_class(Workspace, x), from_none], self.workspace) + return result - uri: str - """URI identifying the resource""" +@dataclass +class WorkspacesListCheckpointsResult: + """Workspace checkpoints in chronological order; empty when the workspace is not enabled.""" - description: str | None = None - """Human-readable description of the resource""" + checkpoints: list[WorkspacesCheckpoints] + """Workspace checkpoints in chronological order. Empty when workspace is not enabled.""" - icons: list[ExternalToolTextResultForLlmContentResourceLinkIcon] | None = None - """Icons associated with this resource""" + @staticmethod + def from_dict(obj: Any) -> 'WorkspacesListCheckpointsResult': + assert isinstance(obj, dict) + checkpoints = from_list(WorkspacesCheckpoints.from_dict, obj.get("checkpoints")) + return WorkspacesListCheckpointsResult(checkpoints) - mime_type: str | None = None - """MIME type of the resource content""" + def to_dict(self) -> dict: + result: dict = {} + result["checkpoints"] = from_list(lambda x: to_class(WorkspacesCheckpoints, x), self.checkpoints) + return result - size: float | None = None - """Size of the resource in bytes""" +@dataclass +class ModelCapabilitiesOverride: + """Override individual model capabilities resolved by the runtime""" - title: str | None = None - """Human-readable display title for the resource""" + 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) -> 'ExternalToolTextResultForLlmContentResourceLink': + def from_dict(obj: Any) -> 'ModelCapabilitiesOverride': assert isinstance(obj, dict) - name = from_str(obj.get("name")) - type = ExternalToolTextResultForLlmContentResourceLinkType(obj.get("type")) - uri = from_str(obj.get("uri")) - description = from_union([from_str, from_none], obj.get("description")) - icons = from_union([lambda x: from_list(ExternalToolTextResultForLlmContentResourceLinkIcon.from_dict, x), from_none], obj.get("icons")) - mime_type = from_union([from_str, from_none], obj.get("mimeType")) - size = from_union([from_float, from_none], obj.get("size")) - title = from_union([from_str, from_none], obj.get("title")) - return ExternalToolTextResultForLlmContentResourceLink(name, type, uri, description, icons, mime_type, size, title) + limits = from_union([ModelCapabilitiesOverrideLimits.from_dict, from_none], obj.get("limits")) + supports = from_union([ModelCapabilitiesOverrideSupports.from_dict, from_none], obj.get("supports")) + return ModelCapabilitiesOverride(limits, supports) def to_dict(self) -> dict: result: dict = {} - result["name"] = from_str(self.name) - result["type"] = to_enum(ExternalToolTextResultForLlmContentResourceLinkType, self.type) - result["uri"] = from_str(self.uri) - 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(ExternalToolTextResultForLlmContentResourceLinkIcon, x), x), from_none], self.icons) - if self.mime_type is not None: - result["mimeType"] = from_union([from_str, from_none], self.mime_type) - if self.size is not None: - result["size"] = from_union([to_float, from_none], self.size) - if self.title is not None: - result["title"] = from_union([from_str, from_none], self.title) + if self.limits is not None: + result["limits"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideLimits, x), from_none], self.limits) + if self.supports is not None: + result["supports"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideSupports, x), from_none], self.supports) return result @dataclass -class InstructionsGetSourcesResult: - """Instruction sources loaded for the session, in merge order.""" - - sources: list[InstructionsSources] - """Instruction sources for the session""" +class PermissionsConfigureAdditionalContentExclusionPolicy: + """Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type.""" + + last_updated_at: float | str + rules: list[PermissionsConfigureAdditionalContentExclusionPolicyRule] + scope: PermissionsConfigureAdditionalContentExclusionPolicyScope + """Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` + enumeration. + """ @staticmethod - def from_dict(obj: Any) -> 'InstructionsGetSourcesResult': + def from_dict(obj: Any) -> 'PermissionsConfigureAdditionalContentExclusionPolicy': assert isinstance(obj, dict) - sources = from_list(InstructionsSources.from_dict, obj.get("sources")) - return InstructionsGetSourcesResult(sources) + last_updated_at = from_union([from_float, from_str], obj.get("last_updated_at")) + rules = from_list(PermissionsConfigureAdditionalContentExclusionPolicyRule.from_dict, obj.get("rules")) + scope = PermissionsConfigureAdditionalContentExclusionPolicyScope(obj.get("scope")) + return PermissionsConfigureAdditionalContentExclusionPolicy(last_updated_at, rules, scope) def to_dict(self) -> dict: result: dict = {} - result["sources"] = from_list(lambda x: to_class(InstructionsSources, x), self.sources) + result["last_updated_at"] = from_union([to_float, from_str], self.last_updated_at) + result["rules"] = from_list(lambda x: to_class(PermissionsConfigureAdditionalContentExclusionPolicyRule, x), self.rules) + result["scope"] = to_enum(PermissionsConfigureAdditionalContentExclusionPolicyScope, self.scope) return result +# Experimental: this type is part of an experimental API and may change or be removed. @dataclass -class MCPConfigAddRequest: - """MCP server name and configuration to add to user configuration.""" - - config: MCPServerConfig - """MCP server configuration (stdio process or remote HTTP/SSE)""" +class QueuePendingItemsResult: + """Snapshot of the session's pending queued items and immediate-steering messages.""" - name: str - """Unique name for the MCP server""" + items: list[QueuePendingItems] + """Pending queued items in submission order. Includes user messages, queued slash commands, + and queued model changes; omits internal system items. + """ + steering_messages: list[str] + """Display text for messages currently in the immediate steering queue (interjections sent + during a running turn). + """ @staticmethod - def from_dict(obj: Any) -> 'MCPConfigAddRequest': + def from_dict(obj: Any) -> 'QueuePendingItemsResult': assert isinstance(obj, dict) - config = MCPServerConfig.from_dict(obj.get("config")) - name = from_str(obj.get("name")) - return MCPConfigAddRequest(config, name) + items = from_list(QueuePendingItems.from_dict, obj.get("items")) + steering_messages = from_list(from_str, obj.get("steeringMessages")) + return QueuePendingItemsResult(items, steering_messages) def to_dict(self) -> dict: result: dict = {} - result["config"] = to_class(MCPServerConfig, self.config) - result["name"] = from_str(self.name) + result["items"] = from_list(lambda x: to_class(QueuePendingItems, x), self.items) + result["steeringMessages"] = from_list(from_str, self.steering_messages) return result @dataclass -class MCPConfigList: - """User-configured MCP servers, keyed by server name.""" +class CommandsRespondToQueuedCommandRequest: + """Queued-command request ID and the result indicating whether the host executed it (and + whether to stop processing further queued commands). + """ + request_id: str + """Request ID from the `command.queued` event the host is responding to.""" - servers: dict[str, MCPServerConfig] - """All MCP servers from user config, keyed by name""" + result: QueuedCommandResult + """Result of the queued command execution.""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigList': + def from_dict(obj: Any) -> 'CommandsRespondToQueuedCommandRequest': assert isinstance(obj, dict) - servers = from_dict(MCPServerConfig.from_dict, obj.get("servers")) - return MCPConfigList(servers) + request_id = from_str(obj.get("requestId")) + result = QueuedCommandResult.from_dict(obj.get("result")) + return CommandsRespondToQueuedCommandRequest(request_id, result) def to_dict(self) -> dict: result: dict = {} - result["servers"] = from_dict(lambda x: to_class(MCPServerConfig, x), self.servers) + result["requestId"] = from_str(self.request_id) + result["result"] = to_class(QueuedCommandResult, self.result) return result @dataclass -class MCPConfigUpdateRequest: - """MCP server name and replacement configuration to write to user configuration.""" +class SendAttachment: + """A user message attachment — a file, directory, code selection, blob, or GitHub reference - config: MCPServerConfig - """MCP server configuration (stdio process or remote HTTP/SSE)""" + File attachment - name: str - """Name of the MCP server to update""" + Directory attachment + + Code selection attachment from an editor + + GitHub issue, pull request, or discussion reference + + Blob attachment with inline base64-encoded data + """ + type: SendAttachmentType + """Attachment type discriminator""" + + display_name: str | None = None + """User-facing display name for the attachment + + User-facing display name for the selection + """ + line_range: SendAttachmentFileLineRange | None = None + """Optional line range to scope the attachment to a specific section of the file""" + + path: str | None = None + """Absolute file path + + Absolute directory path + """ + file_path: str | None = None + """Absolute path to the file containing the selection""" + + selection: SendAttachmentSelectionDetails | None = None + """Position range of the selection within the file""" + + text: str | None = None + """The selected text content""" + + number: int | None = None + """Issue, pull request, or discussion number""" + + reference_type: SendAttachmentGithubReferenceTypeEnum | None = None + """Type of GitHub reference""" + + state: str | None = None + """Current state of the referenced item (e.g., open, closed, merged)""" + + title: str | None = None + """Title of the referenced item""" + + url: str | None = None + """URL to the referenced item on GitHub""" + + data: str | None = None + """Base64-encoded content""" + + mime_type: str | None = None + """MIME type of the inline data""" @staticmethod - def from_dict(obj: Any) -> 'MCPConfigUpdateRequest': + def from_dict(obj: Any) -> 'SendAttachment': assert isinstance(obj, dict) - config = MCPServerConfig.from_dict(obj.get("config")) - name = from_str(obj.get("name")) - return MCPConfigUpdateRequest(config, name) + type = SendAttachmentType(obj.get("type")) + display_name = from_union([from_str, from_none], obj.get("displayName")) + line_range = from_union([SendAttachmentFileLineRange.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([SendAttachmentSelectionDetails.from_dict, from_none], obj.get("selection")) + text = from_union([from_str, from_none], obj.get("text")) + number = from_union([from_int, from_none], obj.get("number")) + reference_type = from_union([SendAttachmentGithubReferenceTypeEnum, 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 SendAttachment(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["config"] = to_class(MCPServerConfig, self.config) - result["name"] = from_str(self.name) - 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""" + result["type"] = to_enum(SendAttachmentType, 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(SendAttachmentFileLineRange, 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(SendAttachmentSelectionDetails, 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([from_int, from_none], self.number) + if self.reference_type is not None: + result["referenceType"] = from_union([lambda x: to_enum(SendAttachmentGithubReferenceTypeEnum, 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: + result["title"] = from_union([from_str, from_none], self.title) + if self.url is not None: + result["url"] = from_union([from_str, from_none], self.url) + if self.data is not None: + result["data"] = from_union([from_str, from_none], self.data) + if self.mime_type is not None: + result["mimeType"] = from_union([from_str, from_none], self.mime_type) + return result - supports: ModelCapabilitiesOverrideSupports | None = None - """Feature flags indicating what the model supports""" +@dataclass +class SendAttachmentSelection: + """Code selection attachment from an editor""" - @staticmethod - def from_dict(obj: Any) -> 'ModelCapabilitiesOverride': - assert isinstance(obj, dict) - limits = from_union([ModelCapabilitiesOverrideLimits.from_dict, from_none], obj.get("limits")) - supports = from_union([ModelCapabilitiesOverrideSupports.from_dict, from_none], obj.get("supports")) - return ModelCapabilitiesOverride(limits, supports) + display_name: str + """User-facing display name for the selection""" - def to_dict(self) -> dict: - result: dict = {} - if self.limits is not None: - result["limits"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideLimits, x), from_none], self.limits) - if self.supports is not None: - result["supports"] = from_union([lambda x: to_class(ModelCapabilitiesOverrideSupports, x), from_none], self.supports) - return result + file_path: str + """Absolute path to the file containing the selection""" -@dataclass -class CommandsRespondToQueuedCommandRequest: - """Queued command request ID and the result indicating whether the client handled it.""" + selection: SendAttachmentSelectionDetails + """Position range of the selection within the file""" - request_id: str - """Request ID from the queued command event""" + text: str + """The selected text content""" - result: QueuedCommandResult - """Result of the queued command execution""" + type: SendAttachmentSelectionType + """Attachment type discriminator""" @staticmethod - def from_dict(obj: Any) -> 'CommandsRespondToQueuedCommandRequest': + def from_dict(obj: Any) -> 'SendAttachmentSelection': assert isinstance(obj, dict) - request_id = from_str(obj.get("requestId")) - result = QueuedCommandResult.from_dict(obj.get("result")) - return CommandsRespondToQueuedCommandRequest(request_id, result) + display_name = from_str(obj.get("displayName")) + file_path = from_str(obj.get("filePath")) + selection = SendAttachmentSelectionDetails.from_dict(obj.get("selection")) + text = from_str(obj.get("text")) + type = SendAttachmentSelectionType(obj.get("type")) + return SendAttachmentSelection(display_name, file_path, selection, text, type) def to_dict(self) -> dict: result: dict = {} - result["requestId"] = from_str(self.request_id) - result["result"] = to_class(QueuedCommandResult, self.result) + result["displayName"] = from_str(self.display_name) + result["filePath"] = from_str(self.file_path) + result["selection"] = to_class(SendAttachmentSelectionDetails, self.selection) + result["text"] = from_str(self.text) + result["type"] = to_enum(SendAttachmentSelectionType, self.type) return result @dataclass @@ -5953,8 +11027,8 @@ class SessionFSSqliteQueryResult: error: SessionFSError | None = None """Describes a filesystem error.""" - last_insert_rowid: float | None = None - """Last inserted row ID (for INSERT)""" + last_insert_rowid: int | None = None + """SQLite last_insert_rowid() value for INSERT.""" @staticmethod def from_dict(obj: Any) -> 'SessionFSSqliteQueryResult': @@ -5963,7 +11037,7 @@ def from_dict(obj: Any) -> 'SessionFSSqliteQueryResult': rows = from_list(lambda x: from_dict(lambda x: x, x), obj.get("rows")) rows_affected = from_int(obj.get("rowsAffected")) error = from_union([SessionFSError.from_dict, from_none], obj.get("error")) - last_insert_rowid = from_union([from_float, from_none], obj.get("lastInsertRowid")) + last_insert_rowid = from_union([from_int, from_none], obj.get("lastInsertRowid")) return SessionFSSqliteQueryResult(columns, rows, rows_affected, error, last_insert_rowid) def to_dict(self) -> dict: @@ -5974,7 +11048,7 @@ def to_dict(self) -> dict: if self.error is not None: result["error"] = from_union([lambda x: to_class(SessionFSError, x), from_none], self.error) if self.last_insert_rowid is not None: - result["lastInsertRowid"] = from_union([to_float, from_none], self.last_insert_rowid) + result["lastInsertRowid"] = from_union([from_int, from_none], self.last_insert_rowid) return result @dataclass @@ -6046,6 +11120,83 @@ def to_dict(self) -> dict: result["error"] = from_union([lambda x: to_class(SessionFSError, x), from_none], self.error) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AgentGetCurrentResult: + """The currently selected custom agent, or null when using the default agent.""" + + agent: AgentInfo | None = None + """Currently selected custom agent, or null if using the default agent""" + + @staticmethod + def from_dict(obj: Any) -> 'AgentGetCurrentResult': + assert isinstance(obj, dict) + agent = from_union([AgentInfo.from_dict, from_none], obj.get("agent")) + return AgentGetCurrentResult(agent) + + def to_dict(self) -> dict: + result: dict = {} + if self.agent is not None: + result["agent"] = from_union([lambda x: to_class(AgentInfo, x), from_none], self.agent) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AgentList: + """Custom agents available to the session.""" + + agents: list[AgentInfo] + """Available custom agents""" + + @staticmethod + def from_dict(obj: Any) -> 'AgentList': + assert isinstance(obj, dict) + agents = from_list(AgentInfo.from_dict, obj.get("agents")) + return AgentList(agents) + + def to_dict(self) -> dict: + result: dict = {} + result["agents"] = from_list(lambda x: to_class(AgentInfo, x), self.agents) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AgentReloadResult: + """Custom agents available to the session after reloading definitions from disk.""" + + agents: list[AgentInfo] + """Reloaded custom agents""" + + @staticmethod + def from_dict(obj: Any) -> 'AgentReloadResult': + assert isinstance(obj, dict) + agents = from_list(AgentInfo.from_dict, obj.get("agents")) + return AgentReloadResult(agents) + + def to_dict(self) -> dict: + result: dict = {} + result["agents"] = from_list(lambda x: to_class(AgentInfo, x), self.agents) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class AgentSelectResult: + """The newly selected custom agent.""" + + agent: AgentInfo + """The newly selected custom agent""" + + @staticmethod + def from_dict(obj: Any) -> 'AgentSelectResult': + assert isinstance(obj, dict) + agent = AgentInfo.from_dict(obj.get("agent")) + return AgentSelectResult(agent) + + def to_dict(self) -> dict: + result: dict = {} + result["agent"] = to_class(AgentInfo, self.agent) + return result + @dataclass class SlashCommandInvocationResult: """Result of invoking the slash command (text output, prompt to send to the agent, or @@ -6124,6 +11275,28 @@ def to_dict(self) -> dict: result["message"] = from_union([from_str, from_none], self.message) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksGetProgressResult: + """Progress information for the task, or null when no task with that ID is tracked.""" + + progress: TaskProgressClass | None = None + """Progress information for the task, discriminated by type. Returns null when no task with + this ID is currently tracked. + """ + + @staticmethod + def from_dict(obj: Any) -> 'TasksGetProgressResult': + assert isinstance(obj, dict) + progress = from_union([TaskProgressClass.from_dict, from_none], obj.get("progress")) + return TasksGetProgressResult(progress) + + def to_dict(self) -> dict: + result: dict = {} + if self.progress is not None: + result["progress"] = from_union([lambda x: to_class(TaskProgressClass, x), from_none], self.progress) + return result + @dataclass class UIElicitationArrayAnyOfField: """Multi-select string field where each option pairs a value with a display label.""" @@ -6140,10 +11313,10 @@ class UIElicitationArrayAnyOfField: description: str | None = None """Help text describing the field.""" - max_items: float | None = None + max_items: int | None = None """Maximum number of items the user may select.""" - min_items: float | None = None + min_items: int | None = None """Minimum number of items the user must select.""" title: str | None = None @@ -6156,8 +11329,8 @@ def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfField': type = UIElicitationArrayAnyOfFieldType(obj.get("type")) default = from_union([lambda x: from_list(from_str, x), from_none], obj.get("default")) description = from_union([from_str, from_none], obj.get("description")) - max_items = from_union([from_float, from_none], obj.get("maxItems")) - min_items = from_union([from_float, from_none], obj.get("minItems")) + max_items = from_union([from_int, from_none], obj.get("maxItems")) + min_items = from_union([from_int, from_none], obj.get("minItems")) title = from_union([from_str, from_none], obj.get("title")) return UIElicitationArrayAnyOfField(items, type, default, description, max_items, min_items, title) @@ -6170,9 +11343,9 @@ def to_dict(self) -> dict: if self.description is not None: result["description"] = from_union([from_str, from_none], self.description) if self.max_items is not None: - result["maxItems"] = from_union([to_float, from_none], self.max_items) + result["maxItems"] = from_union([from_int, from_none], self.max_items) if self.min_items is not None: - result["minItems"] = from_union([to_float, from_none], self.min_items) + result["minItems"] = from_union([from_int, from_none], self.min_items) if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) return result @@ -6193,10 +11366,10 @@ class UIElicitationArrayEnumField: description: str | None = None """Help text describing the field.""" - max_items: float | None = None + max_items: int | None = None """Maximum number of items the user may select.""" - min_items: float | None = None + min_items: int | None = None """Minimum number of items the user must select.""" title: str | None = None @@ -6209,8 +11382,8 @@ def from_dict(obj: Any) -> 'UIElicitationArrayEnumField': type = UIElicitationArrayAnyOfFieldType(obj.get("type")) default = from_union([lambda x: from_list(from_str, x), from_none], obj.get("default")) description = from_union([from_str, from_none], obj.get("description")) - max_items = from_union([from_float, from_none], obj.get("maxItems")) - min_items = from_union([from_float, from_none], obj.get("minItems")) + max_items = from_union([from_int, from_none], obj.get("maxItems")) + min_items = from_union([from_int, from_none], obj.get("minItems")) title = from_union([from_str, from_none], obj.get("title")) return UIElicitationArrayEnumField(items, type, default, description, max_items, min_items, title) @@ -6223,9 +11396,9 @@ def to_dict(self) -> dict: if self.description is not None: result["description"] = from_union([from_str, from_none], self.description) if self.max_items is not None: - result["maxItems"] = from_union([to_float, from_none], self.max_items) + result["maxItems"] = from_union([from_int, from_none], self.max_items) if self.min_items is not None: - result["minItems"] = from_union([to_float, from_none], self.min_items) + result["minItems"] = from_union([from_int, from_none], self.min_items) if self.title is not None: result["title"] = from_union([from_str, from_none], self.title) return result @@ -6282,19 +11455,19 @@ class UIElicitationSchemaProperty: items: UIElicitationArrayFieldItems | None = None """Schema applied to each item in the array.""" - max_items: float | None = None + max_items: int | None = None """Maximum number of items the user may select.""" - min_items: float | None = None + min_items: int | None = None """Minimum number of items the user must select.""" format: UIElicitationSchemaPropertyStringFormat | None = None """Optional format hint that constrains the accepted input.""" - max_length: float | None = None + max_length: int | None = None """Maximum number of characters allowed.""" - min_length: float | None = None + min_length: int | None = None """Minimum number of characters required.""" maximum: float | None = None @@ -6314,11 +11487,11 @@ def from_dict(obj: Any) -> 'UIElicitationSchemaProperty': title = from_union([from_str, from_none], obj.get("title")) one_of = from_union([lambda x: from_list(UIElicitationStringOneOfFieldOneOf.from_dict, x), from_none], obj.get("oneOf")) items = from_union([UIElicitationArrayFieldItems.from_dict, from_none], obj.get("items")) - max_items = from_union([from_float, from_none], obj.get("maxItems")) - min_items = from_union([from_float, from_none], obj.get("minItems")) + max_items = from_union([from_int, from_none], obj.get("maxItems")) + min_items = from_union([from_int, from_none], obj.get("minItems")) 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")) + max_length = from_union([from_int, from_none], obj.get("maxLength")) + min_length = from_union([from_int, 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 UIElicitationSchemaProperty(type, default, description, enum, enum_names, title, one_of, items, max_items, min_items, format, max_length, min_length, maximum, minimum) @@ -6341,15 +11514,15 @@ def to_dict(self) -> dict: if self.items is not None: result["items"] = from_union([lambda x: to_class(UIElicitationArrayFieldItems, x), from_none], self.items) if self.max_items is not None: - result["maxItems"] = from_union([to_float, from_none], self.max_items) + result["maxItems"] = from_union([from_int, from_none], self.max_items) if self.min_items is not None: - result["minItems"] = from_union([to_float, from_none], self.min_items) + result["minItems"] = from_union([from_int, from_none], self.min_items) if self.format is not None: 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) + result["maxLength"] = from_union([from_int, from_none], self.max_length) if self.min_length is not None: - result["minLength"] = from_union([to_float, from_none], self.min_length) + result["minLength"] = from_union([from_int, from_none], self.min_length) if self.maximum is not None: result["maximum"] = from_union([to_float, from_none], self.maximum) if self.minimum is not None: @@ -6380,6 +11553,29 @@ def to_dict(self) -> dict: result["result"] = to_class(UIElicitationResponse, self.result) return result +@dataclass +class UIHandlePendingExitPlanModeRequest: + """Request ID of a pending `exit_plan_mode.requested` event and the user's response.""" + + request_id: str + """The unique request ID from the exit_plan_mode.requested event""" + + response: UIExitPlanModeResponse + """Schema for the `UIExitPlanModeResponse` type.""" + + @staticmethod + def from_dict(obj: Any) -> 'UIHandlePendingExitPlanModeRequest': + assert isinstance(obj, dict) + request_id = from_str(obj.get("requestId")) + response = UIExitPlanModeResponse.from_dict(obj.get("response")) + return UIHandlePendingExitPlanModeRequest(request_id, response) + + def to_dict(self) -> dict: + result: dict = {} + result["requestId"] = from_str(self.request_id) + result["response"] = to_class(UIExitPlanModeResponse, self.response) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class UsageGetMetricsResult: @@ -6395,104 +11591,361 @@ class UsageGetMetricsResult: 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""" + model_metrics: dict[str, UsageMetricsModelMetric] + """Per-model token and request metrics, keyed by model identifier""" + + session_start_time: datetime + """ISO 8601 timestamp when the session started""" + + total_api_duration_ms: int + """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""" + + token_details: dict[str, UsageMetricsTokenDetail] | None = None + """Session-wide per-token-type accumulated token counts""" + + total_nano_aiu: int | None = None + """Session-wide accumulated nano-AI units cost""" + + @staticmethod + def from_dict(obj: Any) -> 'UsageGetMetricsResult': + assert isinstance(obj, dict) + code_changes = UsageMetricsCodeChanges.from_dict(obj.get("codeChanges")) + last_call_input_tokens = from_int(obj.get("lastCallInputTokens")) + last_call_output_tokens = from_int(obj.get("lastCallOutputTokens")) + model_metrics = from_dict(UsageMetricsModelMetric.from_dict, obj.get("modelMetrics")) + session_start_time = from_datetime(obj.get("sessionStartTime")) + total_api_duration_ms = from_int(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")) + token_details = from_union([lambda x: from_dict(UsageMetricsTokenDetail.from_dict, x), from_none], obj.get("tokenDetails")) + total_nano_aiu = from_union([from_int, from_none], obj.get("totalNanoAiu")) + return UsageGetMetricsResult(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model, token_details, total_nano_aiu) + + 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"] = self.session_start_time.isoformat() + result["totalApiDurationMs"] = from_int(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) + if self.token_details is not None: + result["tokenDetails"] = from_union([lambda x: from_dict(lambda x: to_class(UsageMetricsTokenDetail, x), x), from_none], self.token_details) + if self.total_nano_aiu is not None: + result["totalNanoAiu"] = from_union([from_int, from_none], self.total_nano_aiu) + return result + +@dataclass +class CommandList: + """Slash commands available in the session, after applying any include/exclude filters.""" + + commands: list[SlashCommandInfo] + """Commands available in this session""" + + @staticmethod + def from_dict(obj: Any) -> 'CommandList': + assert isinstance(obj, dict) + commands = from_list(SlashCommandInfo.from_dict, obj.get("commands")) + return CommandList(commands) + + def to_dict(self) -> dict: + result: dict = {} + result["commands"] = from_list(lambda x: to_class(SlashCommandInfo, x), self.commands) + return result + +@dataclass +class APIKeyAuthInfo: + """Schema for the `ApiKeyAuthInfo` type.""" + + api_key: str + """The API key. Treat as a secret.""" + + host: str + """Authentication host.""" + + type: APIKeyAuthInfoType + """API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style).""" + + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ + + @staticmethod + def from_dict(obj: Any) -> 'APIKeyAuthInfo': + assert isinstance(obj, dict) + api_key = from_str(obj.get("apiKey")) + host = from_str(obj.get("host")) + type = APIKeyAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return APIKeyAuthInfo(api_key, host, type, copilot_user) + + def to_dict(self) -> dict: + result: dict = {} + result["apiKey"] = from_str(self.api_key) + result["host"] = from_str(self.host) + result["type"] = to_enum(APIKeyAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) + return result + +@dataclass +class CopilotAPITokenAuthInfo: + """Schema for the `CopilotApiTokenAuthInfo` type.""" + + host: Host + """Authentication host (always the public GitHub host).""" + + type: CopilotAPITokenAuthInfoType + """Direct Copilot API authentication via the `GITHUB_COPILOT_API_TOKEN` + `COPILOT_API_URL` + environment-variable pair. The token itself is read from the environment by the runtime, + not carried in this struct. + """ + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ + + @staticmethod + def from_dict(obj: Any) -> 'CopilotAPITokenAuthInfo': + assert isinstance(obj, dict) + host = Host(obj.get("host")) + type = CopilotAPITokenAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return CopilotAPITokenAuthInfo(host, type, copilot_user) + + def to_dict(self) -> dict: + result: dict = {} + result["host"] = to_enum(Host, self.host) + result["type"] = to_enum(CopilotAPITokenAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) + return result + +@dataclass +class EnvAuthInfo: + """Schema for the `EnvAuthInfo` type.""" + + env_var: str + """Name of the environment variable the token was sourced from.""" + + host: str + """Authentication host (e.g. https://github.com or a GHES host).""" + + token: str + """The token value itself. Treat as a secret.""" + + type: EnvAuthInfoType + """Personal access token (PAT) or server-to-server token sourced from an environment + variable. + """ + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ + login: str | None = None + """User login associated with the token. Undefined for server-to-server tokens (those + starting with `ghs_`). + """ + + @staticmethod + def from_dict(obj: Any) -> 'EnvAuthInfo': + assert isinstance(obj, dict) + env_var = from_str(obj.get("envVar")) + host = from_str(obj.get("host")) + token = from_str(obj.get("token")) + type = EnvAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + login = from_union([from_str, from_none], obj.get("login")) + return EnvAuthInfo(env_var, host, token, type, copilot_user, login) + + def to_dict(self) -> dict: + result: dict = {} + result["envVar"] = from_str(self.env_var) + result["host"] = from_str(self.host) + result["token"] = from_str(self.token) + result["type"] = to_enum(EnvAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) + if self.login is not None: + result["login"] = from_union([from_str, from_none], self.login) + return result + +@dataclass +class GhCLIAuthInfo: + """Schema for the `GhCliAuthInfo` type.""" + + host: str + """Authentication host.""" - session_start_time: int - """Session start timestamp (epoch milliseconds)""" + login: str + """User login as reported by `gh auth status`.""" - total_api_duration_ms: float - """Total time spent in model API calls (milliseconds)""" + token: str + """The token returned by `gh auth token`. Treat as a secret.""" - total_premium_request_cost: float - """Total user-initiated premium request cost across all models (may be fractional due to - multipliers) + type: GhCLIAuthInfoType + """Authentication via the `gh` CLI's saved credentials.""" + + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. """ - 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) -> 'GhCLIAuthInfo': + assert isinstance(obj, dict) + host = from_str(obj.get("host")) + login = from_str(obj.get("login")) + token = from_str(obj.get("token")) + type = GhCLIAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return GhCLIAuthInfo(host, login, token, type, copilot_user) - token_details: dict[str, UsageMetricsTokenDetail] | None = None - """Session-wide per-token-type accumulated token counts""" + def to_dict(self) -> dict: + result: dict = {} + result["host"] = from_str(self.host) + result["login"] = from_str(self.login) + result["token"] = from_str(self.token) + result["type"] = to_enum(GhCLIAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) + return result - total_nano_aiu: int | None = None - """Session-wide accumulated nano-AI units cost""" +@dataclass +class HMACAuthInfo: + """Schema for the `HMACAuthInfo` type.""" + + hmac: str + """HMAC secret used to sign requests.""" + + host: Host + """Authentication host. HMAC auth always targets the public GitHub host.""" + + type: HMACAuthInfoType + """HMAC-based authentication used by GitHub-internal services.""" + + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ @staticmethod - def from_dict(obj: Any) -> 'UsageGetMetricsResult': + def from_dict(obj: Any) -> 'HMACAuthInfo': 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")) - token_details = from_union([lambda x: from_dict(UsageMetricsTokenDetail.from_dict, x), from_none], obj.get("tokenDetails")) - total_nano_aiu = from_union([from_int, from_none], obj.get("totalNanoAiu")) - return UsageGetMetricsResult(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model, token_details, total_nano_aiu) + hmac = from_str(obj.get("hmac")) + host = Host(obj.get("host")) + type = HMACAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return HMACAuthInfo(hmac, host, type, copilot_user) 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) - if self.token_details is not None: - result["tokenDetails"] = from_union([lambda x: from_dict(lambda x: to_class(UsageMetricsTokenDetail, x), x), from_none], self.token_details) - if self.total_nano_aiu is not None: - result["totalNanoAiu"] = from_union([from_int, from_none], self.total_nano_aiu) + result["hmac"] = from_str(self.hmac) + result["host"] = to_enum(Host, self.host) + result["type"] = to_enum(HMACAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) return result @dataclass -class WorkspacesGetWorkspaceResult: - """Current workspace metadata for the session, or null when not available.""" +class TokenAuthInfo: + """Schema for the `TokenAuthInfo` type.""" - workspace: Workspace | None = None - """Current workspace metadata, or null if not available""" + host: str + """Authentication host.""" + + token: str + """The token value itself. Treat as a secret.""" + + type: TokenAuthInfoType + """SDK-side token authentication; the host configured the token directly via the SDK.""" + + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ @staticmethod - def from_dict(obj: Any) -> 'WorkspacesGetWorkspaceResult': + def from_dict(obj: Any) -> 'TokenAuthInfo': assert isinstance(obj, dict) - workspace = from_union([Workspace.from_dict, from_none], obj.get("workspace")) - return WorkspacesGetWorkspaceResult(workspace) + host = from_str(obj.get("host")) + token = from_str(obj.get("token")) + type = TokenAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return TokenAuthInfo(host, token, type, copilot_user) def to_dict(self) -> dict: result: dict = {} - result["workspace"] = from_union([lambda x: to_class(Workspace, x), from_none], self.workspace) + result["host"] = from_str(self.host) + result["token"] = from_str(self.token) + result["type"] = to_enum(TokenAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) return result @dataclass -class CommandList: - """Slash commands available in the session, after applying any include/exclude filters.""" +class UserAuthInfo: + """Schema for the `UserAuthInfo` type.""" - commands: list[SlashCommandInfo] - """Commands available in this session""" + host: str + """Authentication host.""" + + login: str + """OAuth user login.""" + + type: UserAuthInfoType + """OAuth user authentication. The token itself is held in the runtime's secret token store + (keyed by host+login) and is NOT carried in this struct. + """ + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ @staticmethod - def from_dict(obj: Any) -> 'CommandList': + def from_dict(obj: Any) -> 'UserAuthInfo': assert isinstance(obj, dict) - commands = from_list(SlashCommandInfo.from_dict, obj.get("commands")) - return CommandList(commands) + host = from_str(obj.get("host")) + login = from_str(obj.get("login")) + type = UserAuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + return UserAuthInfo(host, login, type, copilot_user) def to_dict(self) -> dict: result: dict = {} - result["commands"] = from_list(lambda x: to_class(SlashCommandInfo, x), self.commands) + result["host"] = from_str(self.host) + result["login"] = from_str(self.login) + result["type"] = to_enum(UserAuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) return result @dataclass class PermissionDecisionApproveForLocationApproval: - """The approval to persist for this location + """Approval to persist for this location Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. @@ -6578,7 +12031,7 @@ def to_dict(self) -> dict: @dataclass class PermissionDecisionApproveForIonApproval: - """The approval to add as a session-scoped rule + """Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. @@ -6599,7 +12052,7 @@ class PermissionDecisionApproveForIonApproval: Schema for the `PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess` type. - The approval to persist for this location + Approval to persist for this location Schema for the `PermissionDecisionApproveForLocationApprovalCommands` type. @@ -6619,8 +12072,15 @@ class PermissionDecisionApproveForIonApproval: Schema for the `PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess` type. + + The approval to add as a session-scoped rule + + The approval to persist for this location """ - kind: ApprovalKind + command_identifiers: list[str] | None = None + """Command identifiers covered by this approval.""" + + kind: ApprovalKind | None = None """Approval scoped to specific command identifiers. Approval covering read-only filesystem operations. @@ -6639,9 +12099,6 @@ class PermissionDecisionApproveForIonApproval: Approval covering an extension's request to access a permission-gated capability. """ - command_identifiers: list[str] | None = None - """Command identifiers covered by this approval.""" - server_name: str | None = None """MCP server name.""" @@ -6657,22 +12114,26 @@ class PermissionDecisionApproveForIonApproval: extension_name: str | None = None """Extension name.""" + external_ref_marker_external_ref_user_tool_session_approval: str | None = None + @staticmethod def from_dict(obj: Any) -> 'PermissionDecisionApproveForIonApproval': assert isinstance(obj, dict) - kind = ApprovalKind(obj.get("kind")) command_identifiers = from_union([lambda x: from_list(from_str, x), from_none], obj.get("commandIdentifiers")) + kind = from_union([ApprovalKind, from_none], obj.get("kind")) server_name = from_union([from_str, from_none], obj.get("serverName")) tool_name = from_union([from_none, from_str], obj.get("toolName")) operation = from_union([from_str, from_none], obj.get("operation")) extension_name = from_union([from_str, from_none], obj.get("extensionName")) - return PermissionDecisionApproveForIonApproval(kind, command_identifiers, server_name, tool_name, operation, extension_name) + external_ref_marker_external_ref_user_tool_session_approval = from_union([from_str, from_none], obj.get("__externalRefMarker___ExternalRef_UserToolSessionApproval")) + return PermissionDecisionApproveForIonApproval(command_identifiers, kind, server_name, tool_name, operation, extension_name, external_ref_marker_external_ref_user_tool_session_approval) def to_dict(self) -> dict: result: dict = {} - result["kind"] = to_enum(ApprovalKind, self.kind) if self.command_identifiers is not None: result["commandIdentifiers"] = from_union([lambda x: from_list(from_str, x), from_none], self.command_identifiers) + if self.kind is not None: + result["kind"] = from_union([lambda x: to_enum(ApprovalKind, x), from_none], self.kind) if self.server_name is not None: result["serverName"] = from_union([from_str, from_none], self.server_name) if self.tool_name is not None: @@ -6681,11 +12142,13 @@ def to_dict(self) -> dict: result["operation"] = from_union([from_str, from_none], self.operation) if self.extension_name is not None: result["extensionName"] = from_union([from_str, from_none], self.extension_name) + if self.external_ref_marker_external_ref_user_tool_session_approval is not None: + result["__externalRefMarker___ExternalRef_UserToolSessionApproval"] = from_union([from_str, from_none], self.external_ref_marker_external_ref_user_tool_session_approval) return result @dataclass class PermissionDecisionApproveForSessionApproval: - """The approval to add as a session-scoped rule + """Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) Schema for the `PermissionDecisionApproveForSessionApprovalCommands` type. @@ -6824,6 +12287,425 @@ def to_dict(self) -> dict: result["toolTelemetry"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.tool_telemetry) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class InstalledPlugin: + """Schema for the `InstalledPlugin` type.""" + + enabled: bool + """Whether the plugin is currently enabled""" + + installed_at: str + """Installation timestamp""" + + marketplace: str + """Marketplace the plugin came from (empty string for direct repo installs)""" + + name: str + """Plugin name""" + + cache_path: str | None = None + """Path where the plugin is cached locally""" + + source: InstalledPluginSource | str | None = None + """Source for direct repo installs (when marketplace is empty)""" + + version: str | None = None + """Version installed (if available)""" + + @staticmethod + def from_dict(obj: Any) -> 'InstalledPlugin': + assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) + installed_at = from_str(obj.get("installed_at")) + marketplace = from_str(obj.get("marketplace")) + name = from_str(obj.get("name")) + cache_path = from_union([from_str, from_none], obj.get("cache_path")) + source = from_union([InstalledPluginSource.from_dict, from_str, from_none], obj.get("source")) + version = from_union([from_str, from_none], obj.get("version")) + return InstalledPlugin(enabled, installed_at, marketplace, name, cache_path, source, version) + + def to_dict(self) -> dict: + result: dict = {} + result["enabled"] = from_bool(self.enabled) + result["installed_at"] = from_str(self.installed_at) + result["marketplace"] = from_str(self.marketplace) + result["name"] = from_str(self.name) + if self.cache_path is not None: + result["cache_path"] = from_union([from_str, from_none], self.cache_path) + if self.source is not None: + result["source"] = from_union([lambda x: to_class(InstalledPluginSource, x), from_str, from_none], self.source) + if self.version is not None: + 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 SessionInstalledPlugin: + """Schema for the `SessionInstalledPlugin` type.""" + + enabled: bool + """Whether the plugin is currently enabled""" + + installed_at: str + """Installation timestamp (ISO-8601)""" + + marketplace: str + """Marketplace the plugin came from (empty string for direct repo installs)""" + + name: str + """Plugin name""" + + cache_path: str | None = None + """Path where the plugin is cached locally""" + + source: SessionInstalledPluginSource | str | None = None + """Source descriptor for direct repo installs (when marketplace is empty)""" + + version: str | None = None + """Installed version, if known""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionInstalledPlugin': + assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) + installed_at = from_str(obj.get("installed_at")) + marketplace = from_str(obj.get("marketplace")) + name = from_str(obj.get("name")) + cache_path = from_union([from_str, from_none], obj.get("cache_path")) + source = from_union([SessionInstalledPluginSource.from_dict, from_str, from_none], obj.get("source")) + version = from_union([from_str, from_none], obj.get("version")) + return SessionInstalledPlugin(enabled, installed_at, marketplace, name, cache_path, source, version) + + def to_dict(self) -> dict: + result: dict = {} + result["enabled"] = from_bool(self.enabled) + result["installed_at"] = from_str(self.installed_at) + result["marketplace"] = from_str(self.marketplace) + result["name"] = from_str(self.name) + if self.cache_path is not None: + result["cache_path"] = from_union([from_str, from_none], self.cache_path) + if self.source is not None: + result["source"] = from_union([lambda x: to_class(SessionInstalledPluginSource, x), from_str, from_none], self.source) + if self.version is not None: + 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 SessionEnrichMetadataResult: + """The same metadata records, with summary and context fields backfilled where available.""" + + sessions: list[SessionMetadata] + """Same records, with summary and context backfilled""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionEnrichMetadataResult': + assert isinstance(obj, dict) + sessions = from_list(SessionMetadata.from_dict, obj.get("sessions")) + return SessionEnrichMetadataResult(sessions) + + def to_dict(self) -> dict: + result: dict = {} + result["sessions"] = from_list(lambda x: to_class(SessionMetadata, x), self.sessions) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionList: + """Persisted sessions matching the filter, ordered most-recently-modified first.""" + + sessions: list[SessionMetadata] + """Sessions ordered most-recently-modified first""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionList': + assert isinstance(obj, dict) + sessions = from_list(SessionMetadata.from_dict, obj.get("sessions")) + return SessionList(sessions) + + def to_dict(self) -> dict: + result: dict = {} + result["sessions"] = from_list(lambda x: to_class(SessionMetadata, x), self.sessions) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsEnrichMetadataRequest: + """Session metadata records to enrich with summary and context information.""" + + sessions: list[SessionMetadata] + """Session metadata records to enrich. Records that already have summary and context are + returned unchanged. + """ + + @staticmethod + def from_dict(obj: Any) -> 'SessionsEnrichMetadataRequest': + assert isinstance(obj, dict) + sessions = from_list(SessionMetadata.from_dict, obj.get("sessions")) + return SessionsEnrichMetadataRequest(sessions) + + def to_dict(self) -> dict: + result: dict = {} + result["sessions"] = from_list(lambda x: to_class(SessionMetadata, x), self.sessions) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionMetadataSnapshot: + """Point-in-time snapshot of slow-changing session identifier and state fields""" + + already_in_use: bool + """True when the session was detected to be in use by another process at construction time. + Local consumers may surface a confirmation prompt before fully attaching. Always false + for new sessions. + """ + current_mode: MetadataSnapshotCurrentMode + """The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot')""" + + is_remote: bool + """Whether this is a remote session (i.e., one whose runtime executes elsewhere and is + steered through this process) + """ + modified_time: datetime + """ISO 8601 timestamp of when the session's persisted state was last modified on disk. For + new sessions, equals startTime. For resumed sessions, reflects the previous modification + time at construction. + """ + session_id: str + """The unique identifier of the session""" + + start_time: datetime + """ISO 8601 timestamp of when the session started""" + + working_directory: str + """Absolute path to the session's current working directory""" + + initial_name: str | None = None + """User-provided name supplied at session construction (via `--name`), if any. Immutable + after construction. + """ + remote_metadata: MetadataSnapshotRemoteMetadata | None = None + """Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are + immutable for the lifetime of the session. + """ + selected_model: str | None = None + """Currently selected model identifier, if any""" + + summary: str | None = None + """Short human-readable summary of the session, if known. Omitted when no summary has been + generated. + """ + workspace: WorkspaceSummary | None = None + """Public-facing workspace metadata for this session, or null if the session has no + associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, + internal flags). + """ + workspace_path: str | None = None + """Absolute path to the session's workspace directory on disk, or null if the session has no + associated workspace + """ + + @staticmethod + def from_dict(obj: Any) -> 'SessionMetadataSnapshot': + assert isinstance(obj, dict) + already_in_use = from_bool(obj.get("alreadyInUse")) + current_mode = MetadataSnapshotCurrentMode(obj.get("currentMode")) + is_remote = from_bool(obj.get("isRemote")) + modified_time = from_datetime(obj.get("modifiedTime")) + session_id = from_str(obj.get("sessionId")) + start_time = from_datetime(obj.get("startTime")) + working_directory = from_str(obj.get("workingDirectory")) + initial_name = from_union([from_str, from_none], obj.get("initialName")) + remote_metadata = from_union([MetadataSnapshotRemoteMetadata.from_dict, from_none], obj.get("remoteMetadata")) + selected_model = from_union([from_str, from_none], obj.get("selectedModel")) + summary = from_union([from_str, from_none], obj.get("summary")) + workspace = from_union([WorkspaceSummary.from_dict, from_none], obj.get("workspace")) + workspace_path = from_union([from_none, from_str], obj.get("workspacePath")) + return SessionMetadataSnapshot(already_in_use, current_mode, is_remote, modified_time, session_id, start_time, working_directory, initial_name, remote_metadata, selected_model, summary, workspace, workspace_path) + + def to_dict(self) -> dict: + result: dict = {} + result["alreadyInUse"] = from_bool(self.already_in_use) + result["currentMode"] = to_enum(MetadataSnapshotCurrentMode, self.current_mode) + result["isRemote"] = from_bool(self.is_remote) + result["modifiedTime"] = self.modified_time.isoformat() + result["sessionId"] = from_str(self.session_id) + result["startTime"] = self.start_time.isoformat() + result["workingDirectory"] = from_str(self.working_directory) + if self.initial_name is not None: + result["initialName"] = from_union([from_str, from_none], self.initial_name) + if self.remote_metadata is not None: + result["remoteMetadata"] = from_union([lambda x: to_class(MetadataSnapshotRemoteMetadata, x), from_none], self.remote_metadata) + if self.selected_model is not None: + result["selectedModel"] = from_union([from_str, from_none], self.selected_model) + if self.summary is not None: + result["summary"] = from_union([from_str, from_none], self.summary) + if self.workspace is not None: + result["workspace"] = from_union([lambda x: to_class(WorkspaceSummary, x), from_none], self.workspace) + result["workspacePath"] = from_union([from_none, from_str], self.workspace_path) + return result + +@dataclass +class PermissionsConfigureParams: + """Patch of permission policy fields to apply (omit a field to leave it unchanged).""" + + additional_content_exclusion_policies: list[PermissionsConfigureAdditionalContentExclusionPolicy] | None = None + """If specified, replaces the host-supplied GitHub Content Exclusion policies on the session + (combined with natively-discovered policies when evaluating tool/file access). Omit to + leave the current policies unchanged. + """ + approve_all_read_permission_requests: bool | None = None + """If specified, sets whether path/URL read permission requests are auto-approved. Omit to + leave the current value unchanged. + """ + approve_all_tool_permission_requests: bool | None = None + """If specified, sets whether tool permission requests are auto-approved without prompting. + Omit to leave the current value unchanged. + """ + paths: PermissionPathsConfig | None = None + """If specified, replaces the session's path-permission policy. The runtime constructs the + appropriate PathManager based on these inputs (rooted at the session's working + directory). Omit to leave the current path policy unchanged. + """ + rules: PermissionRulesSet | None = None + """If specified, replaces the session's approved/denied permission rules. Omit to leave the + current rules unchanged. + """ + urls: PermissionUrlsConfig | None = None + """If specified, replaces the session's URL-permission policy. The runtime constructs a + fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy + unchanged. + """ + + @staticmethod + def from_dict(obj: Any) -> 'PermissionsConfigureParams': + assert isinstance(obj, dict) + additional_content_exclusion_policies = from_union([lambda x: from_list(PermissionsConfigureAdditionalContentExclusionPolicy.from_dict, x), from_none], obj.get("additionalContentExclusionPolicies")) + approve_all_read_permission_requests = from_union([from_bool, from_none], obj.get("approveAllReadPermissionRequests")) + approve_all_tool_permission_requests = from_union([from_bool, from_none], obj.get("approveAllToolPermissionRequests")) + paths = from_union([PermissionPathsConfig.from_dict, from_none], obj.get("paths")) + rules = from_union([PermissionRulesSet.from_dict, from_none], obj.get("rules")) + urls = from_union([PermissionUrlsConfig.from_dict, from_none], obj.get("urls")) + return PermissionsConfigureParams(additional_content_exclusion_policies, approve_all_read_permission_requests, approve_all_tool_permission_requests, paths, rules, urls) + + def to_dict(self) -> dict: + result: dict = {} + if self.additional_content_exclusion_policies is not None: + result["additionalContentExclusionPolicies"] = from_union([lambda x: from_list(lambda x: to_class(PermissionsConfigureAdditionalContentExclusionPolicy, x), x), from_none], self.additional_content_exclusion_policies) + if self.approve_all_read_permission_requests is not None: + result["approveAllReadPermissionRequests"] = from_union([from_bool, from_none], self.approve_all_read_permission_requests) + if self.approve_all_tool_permission_requests is not None: + result["approveAllToolPermissionRequests"] = from_union([from_bool, from_none], self.approve_all_tool_permission_requests) + if self.paths is not None: + result["paths"] = from_union([lambda x: to_class(PermissionPathsConfig, x), from_none], self.paths) + if self.rules is not None: + result["rules"] = from_union([lambda x: to_class(PermissionRulesSet, x), from_none], self.rules) + if self.urls is not None: + result["urls"] = from_union([lambda x: to_class(PermissionUrlsConfig, x), from_none], self.urls) + return result + +@dataclass +class SendRequest: + """Parameters for sending a user message to the session""" + + prompt: str + """The user message text""" + + agent_mode: SendAgentMode | None = None + """The UI mode the agent was in when this message was sent. Defaults to the session's + current mode. + """ + attachments: list[SendAttachment] | None = None + """Optional attachments (files, directories, selections, blobs, GitHub references) to + include with the message + """ + billable: bool | None = None + """If false, this message will not trigger a Premium Request Unit charge. User messages + default to billable. + """ + display_prompt: str | None = None + """If provided, this is shown in the timeline instead of `prompt`""" + + mode: SendMode | None = None + """How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` + interjects during an in-progress turn. + """ + prepend: bool | None = None + """If true, adds the message to the front of the queue instead of the end""" + + request_headers: dict[str, str] | None = None + """Custom HTTP headers to include in outbound model requests for this turn. Merged with + session-level provider headers; per-turn headers augment and overwrite session-level + headers with the same key. + """ + required_tool: str | None = None + """If set, the request will fail if the named tool is not available when this message is + among the user messages at the start of the current exchange + """ + source: Any = None + """Optional provenance tag copied to the resulting user.message event. Supported values are + `system`, `command-*`, and `schedule-*`. + """ + traceparent: str | None = None + """W3C Trace Context traceparent header for distributed tracing of this agent turn""" + + tracestate: str | None = None + """W3C Trace Context tracestate header for distributed tracing""" + + wait: bool | None = None + """If true, await completion of the agentic loop for this message before returning. Defaults + to false (fire-and-forget). When true, the result still contains the same `messageId`; + the caller can rely on the agent having processed the message before the call resolves. + """ + + @staticmethod + def from_dict(obj: Any) -> 'SendRequest': + assert isinstance(obj, dict) + prompt = from_str(obj.get("prompt")) + agent_mode = from_union([SendAgentMode, from_none], obj.get("agentMode")) + attachments = from_union([lambda x: from_list(SendAttachment.from_dict, x), from_none], obj.get("attachments")) + billable = from_union([from_bool, from_none], obj.get("billable")) + display_prompt = from_union([from_str, from_none], obj.get("displayPrompt")) + mode = from_union([SendMode, from_none], obj.get("mode")) + prepend = from_union([from_bool, from_none], obj.get("prepend")) + request_headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("requestHeaders")) + required_tool = from_union([from_str, from_none], obj.get("requiredTool")) + source = obj.get("source") + traceparent = from_union([from_str, from_none], obj.get("traceparent")) + tracestate = from_union([from_str, from_none], obj.get("tracestate")) + wait = from_union([from_bool, from_none], obj.get("wait")) + return SendRequest(prompt, agent_mode, attachments, billable, display_prompt, mode, prepend, request_headers, required_tool, source, traceparent, tracestate, wait) + + def to_dict(self) -> dict: + result: dict = {} + result["prompt"] = from_str(self.prompt) + if self.agent_mode is not None: + result["agentMode"] = from_union([lambda x: to_enum(SendAgentMode, x), from_none], self.agent_mode) + if self.attachments is not None: + result["attachments"] = from_union([lambda x: from_list(lambda x: to_class(SendAttachment, x), x), from_none], self.attachments) + if self.billable is not None: + result["billable"] = from_union([from_bool, from_none], self.billable) + if self.display_prompt is not None: + result["displayPrompt"] = from_union([from_str, from_none], self.display_prompt) + if self.mode is not None: + result["mode"] = from_union([lambda x: to_enum(SendMode, x), from_none], self.mode) + if self.prepend is not None: + result["prepend"] = from_union([from_bool, from_none], self.prepend) + if self.request_headers is not None: + result["requestHeaders"] = from_union([lambda x: from_dict(from_str, x), from_none], self.request_headers) + if self.required_tool is not None: + result["requiredTool"] = from_union([from_str, from_none], self.required_tool) + if self.source is not None: + result["source"] = self.source + if self.traceparent is not None: + result["traceparent"] = from_union([from_str, from_none], self.traceparent) + if self.tracestate is not None: + result["tracestate"] = from_union([from_str, from_none], self.tracestate) + if self.wait is not None: + result["wait"] = from_union([from_bool, from_none], self.wait) + return result + @dataclass class UIElicitationSchema: """JSON Schema describing the form fields to present to the user""" @@ -6853,18 +12735,126 @@ def to_dict(self) -> dict: result["required"] = from_union([lambda x: from_list(from_str, x), from_none], self.required) return result +@dataclass +class AuthInfo: + """The new auth credentials to install on the session. When omitted or `undefined`, the call + is a no-op and the session's existing credentials are preserved. The runtime stores the + value verbatim and uses it for outbound model/API requests; it does NOT re-validate or + re-fetch the associated Copilot user response. Several variants carry secret material; + treat this method's params as containing secrets at rest and in transit. + + Schema for the `HMACAuthInfo` type. + + Schema for the `EnvAuthInfo` type. + + Schema for the `TokenAuthInfo` type. + + Schema for the `CopilotApiTokenAuthInfo` type. + + Schema for the `UserAuthInfo` type. + + Schema for the `GhCliAuthInfo` type. + + Schema for the `ApiKeyAuthInfo` type. + """ + host: str + """Authentication host. HMAC auth always targets the public GitHub host. + + Authentication host (e.g. https://github.com or a GHES host). + + Authentication host. + + Authentication host (always the public GitHub host). + """ + type: AuthInfoType + """HMAC-based authentication used by GitHub-internal services. + + Personal access token (PAT) or server-to-server token sourced from an environment + variable. + + SDK-side token authentication; the host configured the token directly via the SDK. + + Direct Copilot API authentication via the `GITHUB_COPILOT_API_TOKEN` + `COPILOT_API_URL` + environment-variable pair. The token itself is read from the environment by the runtime, + not carried in this struct. + + OAuth user authentication. The token itself is held in the runtime's secret token store + (keyed by host+login) and is NOT carried in this struct. + + Authentication via the `gh` CLI's saved credentials. + + API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style). + """ + copilot_user: CopilotUserResponse | None = None + """Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the + GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this + verbatim and does not re-fetch when set. + """ + hmac: str | None = None + """HMAC secret used to sign requests.""" + + env_var: str | None = None + """Name of the environment variable the token was sourced from.""" + + login: str | None = None + """User login associated with the token. Undefined for server-to-server tokens (those + starting with `ghs_`). + + OAuth user login. + + User login as reported by `gh auth status`. + """ + token: str | None = None + """The token value itself. Treat as a secret. + + The token returned by `gh auth token`. Treat as a secret. + """ + api_key: str | None = None + """The API key. Treat as a secret.""" + + @staticmethod + def from_dict(obj: Any) -> 'AuthInfo': + assert isinstance(obj, dict) + host = from_str(obj.get("host")) + type = AuthInfoType(obj.get("type")) + copilot_user = from_union([CopilotUserResponse.from_dict, from_none], obj.get("copilotUser")) + hmac = from_union([from_str, from_none], obj.get("hmac")) + env_var = from_union([from_str, from_none], obj.get("envVar")) + login = from_union([from_str, from_none], obj.get("login")) + token = from_union([from_str, from_none], obj.get("token")) + api_key = from_union([from_str, from_none], obj.get("apiKey")) + return AuthInfo(host, type, copilot_user, hmac, env_var, login, token, api_key) + + def to_dict(self) -> dict: + result: dict = {} + result["host"] = from_str(self.host) + result["type"] = to_enum(AuthInfoType, self.type) + if self.copilot_user is not None: + result["copilotUser"] = from_union([lambda x: to_class(CopilotUserResponse, x), from_none], self.copilot_user) + if self.hmac is not None: + result["hmac"] = from_union([from_str, from_none], self.hmac) + if self.env_var is not None: + result["envVar"] = from_union([from_str, from_none], self.env_var) + if self.login is not None: + result["login"] = from_union([from_str, from_none], self.login) + if self.token is not None: + result["token"] = from_union([from_str, from_none], self.token) + if self.api_key is not None: + result["apiKey"] = from_union([from_str, from_none], self.api_key) + return result + @dataclass class PermissionDecisionApproveForLocation: """Schema for the `PermissionDecisionApproveForLocation` type.""" approval: PermissionDecisionApproveForLocationApproval - """The approval to persist for this location""" + """Approval to persist for this location""" kind: PermissionDecisionApproveForLocationKind - """Approved and persisted for this project location""" + """Approve and persist for this project location""" location_key: str - """The location key (git root or cwd) to persist the approval to""" + """Location key (git root or cwd) to persist the approval to""" @staticmethod def from_dict(obj: Any) -> 'PermissionDecisionApproveForLocation': @@ -6886,13 +12876,13 @@ class PermissionDecisionApproveForSession: """Schema for the `PermissionDecisionApproveForSession` type.""" kind: PermissionDecisionApproveForSessionKind - """Approved and remembered for the rest of the session""" + """Approve and remember for the rest of the session""" approval: PermissionDecisionApproveForSessionApproval | None = None - """The approval to add as a session-scoped rule""" + """Session-scoped approval to remember (tool prompts only; omitted for path/url prompts)""" domain: str | None = None - """The URL domain to approve for this session""" + """URL domain to approve for the rest of the session (URL prompts only)""" @staticmethod def from_dict(obj: Any) -> 'PermissionDecisionApproveForSession': @@ -6942,6 +12932,266 @@ def to_dict(self) -> dict: result["result"] = from_union([lambda x: to_class(ExternalToolTextResultForLlm, x), from_str, from_none], self.result) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionsSetAdditionalPluginsRequest: + """Manager-wide additional plugins to register; replaces any previously-configured set.""" + + plugins: list[InstalledPlugin] + """Manager-wide additional plugins to register. Replaces any previously-configured set. Pass + an empty array to clear. + """ + + @staticmethod + def from_dict(obj: Any) -> 'SessionsSetAdditionalPluginsRequest': + assert isinstance(obj, dict) + plugins = from_list(InstalledPlugin.from_dict, obj.get("plugins")) + return SessionsSetAdditionalPluginsRequest(plugins) + + def to_dict(self) -> dict: + result: dict = {} + result["plugins"] = from_list(lambda x: to_class(InstalledPlugin, x), self.plugins) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class SessionUpdateOptionsParams: + """Patch of mutable session options to apply to the running session.""" + + additional_content_exclusion_policies: list[Any] | None = None + """Additional content-exclusion policies to merge into the session's policy set. Opaque + shape; see `ContentExclusionApiResponse` in the runtime. + """ + agent_context: str | None = None + """Runtime context discriminator (e.g., `cli`, `actions`).""" + + ask_user_disabled: bool | None = None + """Whether to disable the `ask_user` tool (encourages autonomous behavior).""" + + available_tools: list[str] | None = None + """Allowlist of tool names available to this session.""" + + client_name: str | None = None + """Identifier of the client driving the session.""" + + coauthor_enabled: bool | None = None + """Whether to include the `Co-authored-by` trailer in commit messages.""" + + continue_on_auto_mode: bool | None = None + """Whether to allow auto-mode continuation across turns.""" + + copilot_url: str | None = None + """Override URL for the Copilot API endpoint.""" + + custom_agents_local_only: bool | None = None + """Whether to default custom agents to local-only execution.""" + + disabled_instruction_sources: list[str] | None = None + """Instruction source IDs to exclude from the system prompt.""" + + disabled_skills: list[str] | None = None + """Skill IDs that should be excluded from this session.""" + + enable_on_demand_instruction_discovery: bool | None = None + """Whether to discover custom instructions on demand after successful file views (AGENTS.md + / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with + `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. + """ + enable_reasoning_summaries: bool | None = None + """Whether to surface reasoning-summary events from the model.""" + + enable_script_safety: bool | None = None + """Whether shell-script safety heuristics are enabled.""" + + enable_streaming: bool | None = None + """Whether to stream model responses.""" + + env_value_mode: MCPSetEnvValueModeDetails | None = None + """How env values are passed to MCP servers (`direct` inlines literal values; `indirect` + resolves at launch). + """ + events_log_directory: str | None = None + """Override directory for the session-events log. When unset, the runtime's default events + log directory is used. + """ + excluded_tools: list[str] | None = None + """Denylist of tool names for this session.""" + + feature_flags: dict[str, bool] | None = None + """Map of feature-flag IDs to their boolean enabled state.""" + + installed_plugins: list[SessionInstalledPlugin] | None = None + """Full set of installed plugins for the session. Replaces the existing list; the runtime + invalidates the skills cache only when the list materially changes. + """ + integration_id: str | None = None + """Stable integration identifier used for analytics and rate-limit attribution.""" + + is_experimental_mode: bool | None = None + """Whether experimental capabilities are enabled.""" + + log_interactive_shells: bool | None = None + """Whether interactive shell sessions are logged.""" + + lsp_client_name: str | None = None + """Identifier sent to LSP-style integrations.""" + + manage_schedule_enabled: bool | None = None + """Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the + per-session schedule registry; this flag only controls tool exposure (typically gated to + staff users). + """ + model: str | None = None + """The model ID to use for assistant turns.""" + + provider: Any = None + """Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the + runtime. + """ + reasoning_effort: str | None = None + """Reasoning effort for the selected model (model-defined enum).""" + + running_in_interactive_mode: bool | None = None + """Whether the session is running in an interactive UI.""" + + sandbox_config: Any = None + """Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime.""" + + shell_init_profile: str | None = None + """Shell init profile (`None` or `NonInteractive`).""" + + shell_process_flags: list[str] | None = None + """Per-shell process flags (e.g., `pwsh` arguments).""" + + skill_directories: list[str] | None = None + """Additional directories to search for skills.""" + + skip_custom_instructions: bool | None = None + """Whether to skip loading custom instruction sources.""" + + trajectory_file: str | None = None + """Optional path for trajectory output.""" + + working_directory: str | None = None + """Absolute working-directory path for shell tools.""" + + @staticmethod + def from_dict(obj: Any) -> 'SessionUpdateOptionsParams': + assert isinstance(obj, dict) + additional_content_exclusion_policies = from_union([lambda x: from_list(lambda x: x, x), from_none], obj.get("additionalContentExclusionPolicies")) + agent_context = from_union([from_str, from_none], obj.get("agentContext")) + ask_user_disabled = from_union([from_bool, from_none], obj.get("askUserDisabled")) + available_tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("availableTools")) + client_name = from_union([from_str, from_none], obj.get("clientName")) + coauthor_enabled = from_union([from_bool, from_none], obj.get("coauthorEnabled")) + continue_on_auto_mode = from_union([from_bool, from_none], obj.get("continueOnAutoMode")) + copilot_url = from_union([from_str, from_none], obj.get("copilotUrl")) + custom_agents_local_only = from_union([from_bool, from_none], obj.get("customAgentsLocalOnly")) + disabled_instruction_sources = from_union([lambda x: from_list(from_str, x), from_none], obj.get("disabledInstructionSources")) + disabled_skills = from_union([lambda x: from_list(from_str, x), from_none], obj.get("disabledSkills")) + enable_on_demand_instruction_discovery = from_union([from_bool, from_none], obj.get("enableOnDemandInstructionDiscovery")) + enable_reasoning_summaries = from_union([from_bool, from_none], obj.get("enableReasoningSummaries")) + enable_script_safety = from_union([from_bool, from_none], obj.get("enableScriptSafety")) + enable_streaming = from_union([from_bool, from_none], obj.get("enableStreaming")) + env_value_mode = from_union([MCPSetEnvValueModeDetails, from_none], obj.get("envValueMode")) + events_log_directory = from_union([from_str, from_none], obj.get("eventsLogDirectory")) + excluded_tools = from_union([lambda x: from_list(from_str, x), from_none], obj.get("excludedTools")) + feature_flags = from_union([lambda x: from_dict(from_bool, x), from_none], obj.get("featureFlags")) + installed_plugins = from_union([lambda x: from_list(SessionInstalledPlugin.from_dict, x), from_none], obj.get("installedPlugins")) + integration_id = from_union([from_str, from_none], obj.get("integrationId")) + is_experimental_mode = from_union([from_bool, from_none], obj.get("isExperimentalMode")) + log_interactive_shells = from_union([from_bool, from_none], obj.get("logInteractiveShells")) + lsp_client_name = from_union([from_str, from_none], obj.get("lspClientName")) + manage_schedule_enabled = from_union([from_bool, from_none], obj.get("manageScheduleEnabled")) + model = from_union([from_str, from_none], obj.get("model")) + provider = obj.get("provider") + reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort")) + running_in_interactive_mode = from_union([from_bool, from_none], obj.get("runningInInteractiveMode")) + sandbox_config = obj.get("sandboxConfig") + shell_init_profile = from_union([from_str, from_none], obj.get("shellInitProfile")) + shell_process_flags = from_union([lambda x: from_list(from_str, x), from_none], obj.get("shellProcessFlags")) + skill_directories = from_union([lambda x: from_list(from_str, x), from_none], obj.get("skillDirectories")) + skip_custom_instructions = from_union([from_bool, from_none], obj.get("skipCustomInstructions")) + trajectory_file = from_union([from_str, from_none], obj.get("trajectoryFile")) + working_directory = from_union([from_str, from_none], obj.get("workingDirectory")) + return SessionUpdateOptionsParams(additional_content_exclusion_policies, agent_context, ask_user_disabled, available_tools, client_name, coauthor_enabled, continue_on_auto_mode, copilot_url, custom_agents_local_only, disabled_instruction_sources, disabled_skills, enable_on_demand_instruction_discovery, enable_reasoning_summaries, enable_script_safety, enable_streaming, env_value_mode, events_log_directory, excluded_tools, feature_flags, installed_plugins, integration_id, is_experimental_mode, log_interactive_shells, lsp_client_name, manage_schedule_enabled, model, provider, reasoning_effort, running_in_interactive_mode, sandbox_config, shell_init_profile, shell_process_flags, skill_directories, skip_custom_instructions, trajectory_file, working_directory) + + def to_dict(self) -> dict: + result: dict = {} + if self.additional_content_exclusion_policies is not None: + result["additionalContentExclusionPolicies"] = from_union([lambda x: from_list(lambda x: x, x), from_none], self.additional_content_exclusion_policies) + if self.agent_context is not None: + result["agentContext"] = from_union([from_str, from_none], self.agent_context) + if self.ask_user_disabled is not None: + result["askUserDisabled"] = from_union([from_bool, from_none], self.ask_user_disabled) + if self.available_tools is not None: + result["availableTools"] = from_union([lambda x: from_list(from_str, x), from_none], self.available_tools) + if self.client_name is not None: + result["clientName"] = from_union([from_str, from_none], self.client_name) + if self.coauthor_enabled is not None: + result["coauthorEnabled"] = from_union([from_bool, from_none], self.coauthor_enabled) + if self.continue_on_auto_mode is not None: + result["continueOnAutoMode"] = from_union([from_bool, from_none], self.continue_on_auto_mode) + if self.copilot_url is not None: + result["copilotUrl"] = from_union([from_str, from_none], self.copilot_url) + if self.custom_agents_local_only is not None: + result["customAgentsLocalOnly"] = from_union([from_bool, from_none], self.custom_agents_local_only) + if self.disabled_instruction_sources is not None: + result["disabledInstructionSources"] = from_union([lambda x: from_list(from_str, x), from_none], self.disabled_instruction_sources) + if self.disabled_skills is not None: + result["disabledSkills"] = from_union([lambda x: from_list(from_str, x), from_none], self.disabled_skills) + if self.enable_on_demand_instruction_discovery is not None: + result["enableOnDemandInstructionDiscovery"] = from_union([from_bool, from_none], self.enable_on_demand_instruction_discovery) + if self.enable_reasoning_summaries is not None: + result["enableReasoningSummaries"] = from_union([from_bool, from_none], self.enable_reasoning_summaries) + if self.enable_script_safety is not None: + result["enableScriptSafety"] = from_union([from_bool, from_none], self.enable_script_safety) + if self.enable_streaming is not None: + result["enableStreaming"] = from_union([from_bool, from_none], self.enable_streaming) + if self.env_value_mode is not None: + result["envValueMode"] = from_union([lambda x: to_enum(MCPSetEnvValueModeDetails, x), from_none], self.env_value_mode) + if self.events_log_directory is not None: + result["eventsLogDirectory"] = from_union([from_str, from_none], self.events_log_directory) + if self.excluded_tools is not None: + result["excludedTools"] = from_union([lambda x: from_list(from_str, x), from_none], self.excluded_tools) + if self.feature_flags is not None: + result["featureFlags"] = from_union([lambda x: from_dict(from_bool, x), from_none], self.feature_flags) + if self.installed_plugins is not None: + result["installedPlugins"] = from_union([lambda x: from_list(lambda x: to_class(SessionInstalledPlugin, x), x), from_none], self.installed_plugins) + if self.integration_id is not None: + result["integrationId"] = from_union([from_str, from_none], self.integration_id) + if self.is_experimental_mode is not None: + result["isExperimentalMode"] = from_union([from_bool, from_none], self.is_experimental_mode) + if self.log_interactive_shells is not None: + result["logInteractiveShells"] = from_union([from_bool, from_none], self.log_interactive_shells) + if self.lsp_client_name is not None: + result["lspClientName"] = from_union([from_str, from_none], self.lsp_client_name) + if self.manage_schedule_enabled is not None: + result["manageScheduleEnabled"] = from_union([from_bool, from_none], self.manage_schedule_enabled) + if self.model is not None: + result["model"] = from_union([from_str, from_none], self.model) + if self.provider is not None: + result["provider"] = self.provider + if self.reasoning_effort is not None: + result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort) + if self.running_in_interactive_mode is not None: + result["runningInInteractiveMode"] = from_union([from_bool, from_none], self.running_in_interactive_mode) + if self.sandbox_config is not None: + result["sandboxConfig"] = self.sandbox_config + if self.shell_init_profile is not None: + result["shellInitProfile"] = from_union([from_str, from_none], self.shell_init_profile) + if self.shell_process_flags is not None: + result["shellProcessFlags"] = from_union([lambda x: from_list(from_str, x), from_none], self.shell_process_flags) + if self.skill_directories is not None: + result["skillDirectories"] = from_union([lambda x: from_list(from_str, x), from_none], self.skill_directories) + if self.skip_custom_instructions is not None: + result["skipCustomInstructions"] = from_union([from_bool, from_none], self.skip_custom_instructions) + if self.trajectory_file is not None: + result["trajectoryFile"] = from_union([from_str, from_none], self.trajectory_file) + if self.working_directory is not None: + result["workingDirectory"] = from_union([from_str, from_none], self.working_directory) + return result + @dataclass class UIElicitationRequest: """Prompt message and JSON schema describing the form fields to elicit from the user.""" @@ -6965,9 +13215,33 @@ def to_dict(self) -> dict: result["requestedSchema"] = to_class(UIElicitationSchema, self.requested_schema) return result +@dataclass +class SessionSetCredentialsParams: + """New auth credentials to install on the session. Omit to leave credentials unchanged.""" + + credentials: AuthInfo | None = None + """The new auth credentials to install on the session. When omitted or `undefined`, the call + is a no-op and the session's existing credentials are preserved. The runtime stores the + value verbatim and uses it for outbound model/API requests; it does NOT re-validate or + re-fetch the associated Copilot user response. Several variants carry secret material; + treat this method's params as containing secrets at rest and in transit. + """ + + @staticmethod + def from_dict(obj: Any) -> 'SessionSetCredentialsParams': + assert isinstance(obj, dict) + credentials = from_union([AuthInfo.from_dict, from_none], obj.get("credentials")) + return SessionSetCredentialsParams(credentials) + + def to_dict(self) -> dict: + result: dict = {} + if self.credentials is not None: + result["credentials"] = from_union([lambda x: to_class(AuthInfo, x), from_none], self.credentials) + return result + @dataclass class PermissionDecision: - """Decision to apply to a pending permission request. + """The client's response to the pending permission prompt Schema for the `PermissionDecisionApproveOnce` type. @@ -6980,35 +13254,99 @@ class PermissionDecision: Schema for the `PermissionDecisionReject` type. Schema for the `PermissionDecisionUserNotAvailable` type. + + Schema for the `PermissionDecisionApproved` type. + + Schema for the `PermissionDecisionApprovedForSession` type. + + Schema for the `PermissionDecisionApprovedForLocation` type. + + Schema for the `PermissionDecisionCancelled` type. + + Schema for the `PermissionDecisionDeniedByRules` type. + + Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. + + Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. + + Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. + + Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. """ kind: PermissionDecisionKind - """The permission request was approved for this one instance + """Approve this single request only + + Approve and remember for the rest of the session + + Approve and persist for this project location + + Approve and persist across sessions (URL prompts only) + + Reject the request + + No user is available to confirm the request + + The permission request was approved Approved and remembered for the rest of the session Approved and persisted for this project location - Approved and persisted across sessions + The permission request was cancelled before a response was used + + 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 because user confirmation was unavailable + Denied by the organization's content exclusion policy + + Denied by a permission request hook registered by an extension or plugin """ approval: PermissionDecisionApproveForIonApproval | None = None - """The approval to add as a session-scoped rule + """Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) + + Approval to persist for this location + + The approval to add as a session-scoped rule The approval to persist for this location """ domain: str | None = None - """The URL domain to approve for this session + """URL domain to approve for the rest of the session (URL prompts only) - The URL domain to approve permanently + URL domain to approve permanently """ location_key: str | None = None - """The location key (git root or cwd) to persist the approval to""" + """Location key (git root or cwd) to persist the approval to + The location key (git root or cwd) to persist the approval to + """ feedback: str | None = None - """Optional feedback from the user explaining the denial""" + """Optional feedback explaining the rejection + + Optional feedback from the user explaining the denial + """ + reason: str | None = None + """Optional explanation of why the request was cancelled""" + + rules: list[PermissionRule] | None = None + """Rules that denied the request""" + + force_reject: bool | None = None + """Whether to force-reject the current agent turn""" + + 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) -> 'PermissionDecision': @@ -7018,7 +13356,13 @@ def from_dict(obj: Any) -> 'PermissionDecision': domain = from_union([from_str, from_none], obj.get("domain")) location_key = from_union([from_str, from_none], obj.get("locationKey")) feedback = from_union([from_str, from_none], obj.get("feedback")) - return PermissionDecision(kind, approval, domain, location_key, feedback) + reason = from_union([from_str, from_none], obj.get("reason")) + rules = from_union([lambda x: from_list(PermissionRule.from_dict, x), from_none], obj.get("rules")) + force_reject = from_union([from_bool, from_none], obj.get("forceReject")) + 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 PermissionDecision(kind, approval, domain, location_key, feedback, reason, rules, force_reject, message, path, interrupt) def to_dict(self) -> dict: result: dict = {} @@ -7031,6 +13375,18 @@ def to_dict(self) -> dict: result["locationKey"] = from_union([from_str, from_none], self.location_key) if self.feedback is not None: result["feedback"] = from_union([from_str, from_none], self.feedback) + if self.reason is not None: + result["reason"] = from_union([from_str, from_none], self.reason) + if self.rules is not None: + result["rules"] = from_union([lambda x: from_list(lambda x: to_class(PermissionRule, x), x), from_none], self.rules) + if self.force_reject is not None: + result["forceReject"] = from_union([from_bool, from_none], self.force_reject) + if self.message is not None: + result["message"] = from_union([from_str, from_none], self.message) + if self.path is not None: + result["path"] = from_union([from_str, from_none], self.path) + if self.interrupt is not None: + result["interrupt"] = from_union([from_bool, from_none], self.interrupt) return result @dataclass @@ -7041,7 +13397,7 @@ class PermissionDecisionRequest: """Request ID of the pending permission request""" result: PermissionDecision - """Decision to apply to a pending permission request.""" + """The client's response to the pending permission prompt""" @staticmethod def from_dict(obj: Any) -> 'PermissionDecisionRequest': @@ -7056,6 +13412,99 @@ def to_dict(self) -> dict: result["result"] = to_class(PermissionDecision, self.result) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MCPExecuteSamplingParams: + """Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference.""" + + mcp_request_id: float | str + """The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate + the inference with the originating MCP request for telemetry; this is distinct from + `requestId` (which is the schema-level cancellation handle). + """ + request: dict[str, Any] + """Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. + Treated as opaque at the schema layer; the runtime converts the embedded MCP messages + into the OpenAI chat-completion shape internally. + """ + request_id: str + """Caller-provided unique identifier for this sampling execution. Use this same ID with + cancelSamplingExecution to cancel the in-flight call. Must be unique within the session + for the lifetime of the call. + """ + server_name: str + """Name of the MCP server that initiated the sampling request""" + + @staticmethod + def from_dict(obj: Any) -> 'MCPExecuteSamplingParams': + assert isinstance(obj, dict) + mcp_request_id = from_union([from_float, from_str], obj.get("mcpRequestId")) + request = from_dict(lambda x: x, obj.get("request")) + request_id = from_str(obj.get("requestId")) + server_name = from_str(obj.get("serverName")) + return MCPExecuteSamplingParams(mcp_request_id, request, request_id, server_name) + + def to_dict(self) -> dict: + result: dict = {} + result["mcpRequestId"] = from_union([to_float, from_str], self.mcp_request_id) + result["request"] = from_dict(lambda x: x, self.request) + result["requestId"] = from_str(self.request_id) + result["serverName"] = from_str(self.server_name) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataContextInfoRequest: + """Model identifier and token limits used to compute the context-info breakdown.""" + + output_token_limit: int + """Maximum output tokens allowed by the target model. Pass 0 if unknown.""" + + prompt_token_limit: int + """Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default.""" + + selected_model: str | None = None + """Model identifier used for tokenization. Omit to use the session default. Used both for + token counting and to compute display values. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataContextInfoRequest': + assert isinstance(obj, dict) + output_token_limit = from_int(obj.get("outputTokenLimit")) + prompt_token_limit = from_int(obj.get("promptTokenLimit")) + selected_model = from_union([from_str, from_none], obj.get("selectedModel")) + return MetadataContextInfoRequest(output_token_limit, prompt_token_limit, selected_model) + + def to_dict(self) -> dict: + result: dict = {} + result["outputTokenLimit"] = from_int(self.output_token_limit) + result["promptTokenLimit"] = from_int(self.prompt_token_limit) + if self.selected_model is not None: + result["selectedModel"] = from_union([from_str, from_none], self.selected_model) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class MetadataRecomputeContextTokensRequest: + """Model identifier to use when re-tokenizing the session's existing messages.""" + + model_id: str + """Model identifier used for tokenization. The runtime token-counts both chat-context and + system-context messages against this model. + """ + + @staticmethod + def from_dict(obj: Any) -> 'MetadataRecomputeContextTokensRequest': + assert isinstance(obj, dict) + model_id = from_str(obj.get("modelId")) + return MetadataRecomputeContextTokensRequest(model_id) + + def to_dict(self) -> dict: + result: dict = {} + result["modelId"] = from_str(self.model_id) + return result + @dataclass class ModelCapabilities: """Model capabilities and limits""" @@ -7207,6 +13656,38 @@ def to_dict(self) -> dict: result["reasoningSummary"] = from_union([lambda x: to_enum(ReasoningSummary, x), from_none], self.reasoning_summary) return result +class PermissionsSetApproveAllSource(Enum): + """Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers.""" + + AUTOPILOT_CONFIRMATION = "autopilot_confirmation" + CLI_FLAG = "cli_flag" + RPC = "rpc" + SLASH_COMMAND = "slash_command" + +@dataclass +class PermissionsSetApproveAllRequest: + """Allow-all toggle for tool permission requests, with an optional telemetry source.""" + + enabled: bool + """Whether to auto-approve all tool permission requests""" + + source: PermissionsSetApproveAllSource | None = None + """Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers.""" + + @staticmethod + def from_dict(obj: Any) -> 'PermissionsSetApproveAllRequest': + assert isinstance(obj, dict) + enabled = from_bool(obj.get("enabled")) + source = from_union([PermissionsSetApproveAllSource, from_none], obj.get("source")) + return PermissionsSetApproveAllRequest(enabled, source) + + def to_dict(self) -> dict: + result: dict = {} + result["enabled"] = from_bool(self.enabled) + if self.source is not None: + result["source"] = from_union([lambda x: to_enum(PermissionsSetApproveAllSource, x), from_none], self.source) + return result + # Experimental: this type is part of an experimental API and may change or be removed. @dataclass class TaskAgentInfo: @@ -7328,6 +13809,14 @@ def to_dict(self) -> dict: class TaskInfo: """Schema for the `TaskInfo` type. + The first sync-waiting task (agent first, then shell) that can currently be promoted to + background mode. Omitted if no such task exists. The returned task is guaranteed to have + executionMode='sync' and canPromoteToBackground=true at the time of the call. + + The promoted task as it now exists in background mode, omitted if no promotable task was + waiting. Atomic operation: avoids the race window of getCurrentPromotable + + promoteToBackground. + Schema for the `TaskAgentInfo` type. Schema for the `TaskShellInfo` type. @@ -7344,7 +13833,7 @@ class TaskInfo: status: TaskStatus """Current lifecycle status of the task""" - type: TaskInfoType + type: TaskAgentProgressType """Task kind""" active_started_at: datetime | None = None @@ -7410,7 +13899,7 @@ def from_dict(obj: Any) -> 'TaskInfo': id = from_str(obj.get("id")) started_at = from_datetime(obj.get("startedAt")) status = TaskStatus(obj.get("status")) - type = TaskInfoType(obj.get("type")) + type = TaskAgentProgressType(obj.get("type")) active_started_at = from_union([from_datetime, from_none], obj.get("activeStartedAt")) active_time_ms = from_union([from_int, from_none], obj.get("activeTimeMs")) agent_type = from_union([from_str, from_none], obj.get("agentType")) @@ -7436,7 +13925,7 @@ def to_dict(self) -> dict: result["id"] = from_str(self.id) result["startedAt"] = self.started_at.isoformat() result["status"] = to_enum(TaskStatus, self.status) - result["type"] = to_enum(TaskInfoType, self.type) + result["type"] = to_enum(TaskAgentProgressType, self.type) if self.active_started_at is not None: result["activeStartedAt"] = from_union([lambda x: x.isoformat(), from_none], self.active_started_at) if self.active_time_ms is not None: @@ -7492,17 +13981,69 @@ def to_dict(self) -> dict: result["tasks"] = from_list(lambda x: to_class(TaskInfo, x), self.tasks) return result +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksGetCurrentPromotableResult: + """The first sync-waiting task that can currently be promoted to background mode.""" + + task: TaskInfo | None = None + """The first sync-waiting task (agent first, then shell) that can currently be promoted to + background mode. Omitted if no such task exists. The returned task is guaranteed to have + executionMode='sync' and canPromoteToBackground=true at the time of the call. + """ + + @staticmethod + def from_dict(obj: Any) -> 'TasksGetCurrentPromotableResult': + assert isinstance(obj, dict) + task = from_union([TaskInfo.from_dict, from_none], obj.get("task")) + return TasksGetCurrentPromotableResult(task) + + def to_dict(self) -> dict: + result: dict = {} + if self.task is not None: + result["task"] = from_union([lambda x: to_class(TaskInfo, x), from_none], self.task) + return result + +# Experimental: this type is part of an experimental API and may change or be removed. +@dataclass +class TasksPromoteCurrentToBackgroundResult: + """The promoted task as it now exists in background mode, omitted if no promotable task was + waiting. + """ + task: TaskInfo | None = None + """The promoted task as it now exists in background mode, omitted if no promotable task was + waiting. Atomic operation: avoids the race window of getCurrentPromotable + + promoteToBackground. + """ + + @staticmethod + def from_dict(obj: Any) -> 'TasksPromoteCurrentToBackgroundResult': + assert isinstance(obj, dict) + task = from_union([TaskInfo.from_dict, from_none], obj.get("task")) + return TasksPromoteCurrentToBackgroundResult(task) + + def to_dict(self) -> dict: + result: dict = {} + if self.task is not None: + result["task"] = from_union([lambda x: to_class(TaskInfo, x), from_none], self.task) + return result + @dataclass class RPC: + abort_request: AbortRequest + abort_result: AbortResult account_get_quota_request: AccountGetQuotaRequest account_get_quota_result: AccountGetQuotaResult account_quota_snapshot: AccountQuotaSnapshot agent_get_current_result: AgentGetCurrentResult agent_info: AgentInfo + agent_info_source: AgentInfoSource agent_list: AgentList agent_reload_result: AgentReloadResult agent_select_request: AgentSelectRequest agent_select_result: AgentSelectResult + api_key_auth_info: APIKeyAuthInfo + auth_info: AuthInfo auth_info_type: AuthInfoType command_list: CommandList commands_handle_pending_command_request: CommandsHandlePendingCommandRequest @@ -7518,9 +14059,28 @@ class RPC: connect_request: ConnectRequest connect_result: ConnectResult content_filter_mode: ContentFilterMode + copilot_api_token_auth_info: CopilotAPITokenAuthInfo + copilot_user_response: CopilotUserResponse + copilot_user_response_endpoints: CopilotUserResponseEndpoints + copilot_user_response_quota_snapshots: dict[str, CopilotUserResponseQuotaSnapshots | None] + copilot_user_response_quota_snapshots_chat: CopilotUserResponseQuotaSnapshotsChat + copilot_user_response_quota_snapshots_completions: CopilotUserResponseQuotaSnapshotsCompletions + copilot_user_response_quota_snapshots_premium_interactions: CopilotUserResponseQuotaSnapshotsPremiumInteractions current_model: CurrentModel discovered_mcp_server: DiscoveredMCPServer discovered_mcp_server_type: DiscoveredMCPServerType + enqueue_command_params: EnqueueCommandParams + enqueue_command_result: EnqueueCommandResult + env_auth_info: EnvAuthInfo + event_log_read_request: EventLogReadRequest + event_log_release_interest_result: EventLogReleaseInterestResult + event_log_tail_result: EventLogTailResult + event_log_types: list[str] | EventLogTypes + events_agent_scope: EventsAgentScope + events_cursor_status: EventsCursorStatus + events_read_result: EventsReadResult + execute_command_params: ExecuteCommandParams + execute_command_result: ExecuteCommandResult extension: Extension extension_list: ExtensionList extensions_disable_request: ExtensionsDisableRequest @@ -7544,18 +14104,31 @@ class RPC: filter_mapping: dict[str, ContentFilterMode] | ContentFilterMode fleet_start_request: FleetStartRequest fleet_start_result: FleetStartResult + gh_cli_auth_info: GhCLIAuthInfo handle_pending_tool_call_request: HandlePendingToolCallRequest handle_pending_tool_call_result: HandlePendingToolCallResult + history_abort_manual_compaction_result: HistoryAbortManualCompactionResult + history_cancel_background_compaction_result: HistoryCancelBackgroundCompactionResult history_compact_context_window: HistoryCompactContextWindow history_compact_result: HistoryCompactResult + history_summarize_for_handoff_result: HistorySummarizeForHandoffResult history_truncate_request: HistoryTruncateRequest history_truncate_result: HistoryTruncateResult + hmac_auth_info: HMACAuthInfo + installed_plugin: InstalledPlugin + installed_plugin_source: InstalledPluginSource | str + installed_plugin_source_github: InstalledPluginSourceGithub + installed_plugin_source_local: InstalledPluginSourceLocal + installed_plugin_source_url: InstalledPluginSourceURL instructions_get_sources_result: InstructionsGetSourcesResult instructions_sources: InstructionsSources instructions_sources_location: InstructionsSourcesLocation instructions_sources_type: InstructionsSourcesType log_request: LogRequest log_result: LogResult + lsp_initialize_request: LspInitializeRequest + mcp_cancel_sampling_execution_params: MCPCancelSamplingExecutionParams + mcp_cancel_sampling_execution_result: MCPCancelSamplingExecutionResult mcp_config_add_request: MCPConfigAddRequest mcp_config_disable_request: MCPConfigDisableRequest mcp_config_enable_request: MCPConfigEnableRequest @@ -7566,8 +14139,14 @@ class RPC: mcp_discover_request: MCPDiscoverRequest mcp_discover_result: MCPDiscoverResult mcp_enable_request: MCPEnableRequest + mcp_execute_sampling_params: MCPExecuteSamplingParams + mcp_execute_sampling_request: dict[str, Any] + mcp_execute_sampling_result: dict[str, Any] mcp_oauth_login_request: MCPOauthLoginRequest mcp_oauth_login_result: MCPOauthLoginResult + mcp_remove_git_hub_result: MCPRemoveGitHubResult + mcp_sampling_execution_action: MCPSamplingExecutionAction + mcp_sampling_execution_result: MCPSamplingExecutionResult mcp_server: MCPServer mcp_server_config: MCPServerConfig mcp_server_config_http: MCPServerConfigHTTP @@ -7576,6 +14155,22 @@ class RPC: mcp_server_config_http_type: MCPServerConfigHTTPType mcp_server_config_stdio: MCPServerConfigStdio mcp_server_list: MCPServerList + mcp_set_env_value_mode_details: MCPSetEnvValueModeDetails + mcp_set_env_value_mode_params: MCPSetEnvValueModeParams + mcp_set_env_value_mode_result: MCPSetEnvValueModeResult + metadata_context_info_request: MetadataContextInfoRequest + metadata_context_info_result: MetadataContextInfoResult + metadata_is_processing_result: MetadataIsProcessingResult + metadata_recompute_context_tokens_request: MetadataRecomputeContextTokensRequest + metadata_recompute_context_tokens_result: MetadataRecomputeContextTokensResult + metadata_record_context_change_request: MetadataRecordContextChangeRequest + metadata_record_context_change_result: MetadataRecordContextChangeResult + metadata_set_working_directory_request: MetadataSetWorkingDirectoryRequest + metadata_set_working_directory_result: MetadataSetWorkingDirectoryResult + metadata_snapshot_current_mode: MetadataSnapshotCurrentMode + metadata_snapshot_remote_metadata: MetadataSnapshotRemoteMetadata + metadata_snapshot_remote_metadata_repository: MetadataSnapshotRemoteMetadataRepository + metadata_snapshot_remote_metadata_task_type: MetadataSnapshotRemoteMetadataTaskType model: Model model_billing: ModelBilling model_billing_token_prices: ModelBillingTokenPrices @@ -7592,13 +14187,23 @@ class RPC: model_picker_price_category: ModelPickerPriceCategory model_policy: ModelPolicy model_policy_state: ModelPolicyState + model_set_reasoning_effort_request: ModelSetReasoningEffortRequest + model_set_reasoning_effort_result: ModelSetReasoningEffortResult models_list_request: ModelsListRequest model_switch_to_request: ModelSwitchToRequest model_switch_to_result: ModelSwitchToResult mode_set_request: ModeSetRequest name_get_result: NameGetResult + name_set_auto_request: NameSetAutoRequest + name_set_auto_result: NameSetAutoResult name_set_request: NameSetRequest + options_update_env_value_mode: MCPSetEnvValueModeDetails + pending_permission_request: PendingPermissionRequest + pending_permission_request_list: PendingPermissionRequestList permission_decision: PermissionDecision + permission_decision_approved: PermissionDecisionApproved + permission_decision_approved_for_location: PermissionDecisionApprovedForLocation + permission_decision_approved_for_session: PermissionDecisionApprovedForSession permission_decision_approve_for_location: PermissionDecisionApproveForLocation permission_decision_approve_for_location_approval: PermissionDecisionApproveForLocationApproval permission_decision_approve_for_location_approval_commands: PermissionDecisionApproveForLocationApprovalCommands @@ -7623,14 +14228,50 @@ class RPC: permission_decision_approve_for_session_approval_write: PermissionDecisionApproveForSessionApprovalWrite permission_decision_approve_once: PermissionDecisionApproveOnce permission_decision_approve_permanently: PermissionDecisionApprovePermanently + permission_decision_cancelled: PermissionDecisionCancelled + permission_decision_denied_by_content_exclusion_policy: PermissionDecisionDeniedByContentExclusionPolicy + permission_decision_denied_by_permission_request_hook: PermissionDecisionDeniedByPermissionRequestHook + permission_decision_denied_by_rules: PermissionDecisionDeniedByRules + permission_decision_denied_interactively_by_user: PermissionDecisionDeniedInteractivelyByUser + permission_decision_denied_no_approval_rule_and_could_not_request_from_user: PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser permission_decision_reject: PermissionDecisionReject permission_decision_request: PermissionDecisionRequest permission_decision_user_not_available: PermissionDecisionUserNotAvailable + permission_paths_add_params: PermissionPathsAddParams + permission_paths_allowed_check_params: PermissionPathsAllowedCheckParams + permission_paths_allowed_check_result: PermissionPathsAllowedCheckResult + permission_paths_config: PermissionPathsConfig + permission_paths_list: PermissionPathsList + permission_paths_update_primary_params: PermissionPathsUpdatePrimaryParams + permission_paths_workspace_check_params: PermissionPathsWorkspaceCheckParams + permission_paths_workspace_check_result: PermissionPathsWorkspaceCheckResult + permission_prompt_shown_notification: PermissionPromptShownNotification permission_request_result: PermissionRequestResult + permission_rules_set: PermissionRulesSet + permissions_configure_additional_content_exclusion_policy: PermissionsConfigureAdditionalContentExclusionPolicy + permissions_configure_additional_content_exclusion_policy_rule: PermissionsConfigureAdditionalContentExclusionPolicyRule + permissions_configure_additional_content_exclusion_policy_rule_source: PermissionsConfigureAdditionalContentExclusionPolicyRuleSource + permissions_configure_additional_content_exclusion_policy_scope: PermissionsConfigureAdditionalContentExclusionPolicyScope + permissions_configure_params: PermissionsConfigureParams + permissions_configure_result: PermissionsConfigureResult + permissions_modify_rules_params: PermissionsModifyRulesParams + permissions_modify_rules_result: PermissionsModifyRulesResult + permissions_modify_rules_scope: PermissionsModifyRulesScope + permissions_notify_prompt_shown_result: PermissionsNotifyPromptShownResult + permissions_paths_add_result: PermissionsPathsAddResult + permissions_paths_list_request: PermissionsPathsListRequest + permissions_paths_update_primary_result: PermissionsPathsUpdatePrimaryResult + permissions_pending_requests_request: PermissionsPendingRequestsRequest permissions_reset_session_approvals_request: PermissionsResetSessionApprovalsRequest permissions_reset_session_approvals_result: PermissionsResetSessionApprovalsResult permissions_set_approve_all_request: PermissionsSetApproveAllRequest permissions_set_approve_all_result: PermissionsSetApproveAllResult + permissions_set_approve_all_source: PermissionsSetApproveAllSource + permissions_set_required_request: PermissionsSetRequiredRequest + permissions_set_required_result: PermissionsSetRequiredResult + permissions_urls_set_unrestricted_mode_result: PermissionsUrlsSetUnrestrictedModeResult + permission_urls_config: PermissionUrlsConfig + permission_urls_set_unrestricted_mode_params: PermissionUrlsSetUnrestrictedModeParams ping_request: PingRequest ping_result: PingResult plan_read_result: PlanReadResult @@ -7640,13 +14281,45 @@ class RPC: queued_command_handled: QueuedCommandHandled queued_command_not_handled: QueuedCommandNotHandled queued_command_result: QueuedCommandResult + queue_pending_items: QueuePendingItems + queue_pending_items_kind: QueuePendingItemsKind + queue_pending_items_result: QueuePendingItemsResult + queue_remove_most_recent_result: QueueRemoveMostRecentResult + register_event_interest_params: RegisterEventInterestParams + register_event_interest_result: RegisterEventInterestResult + release_event_interest_params: ReleaseEventInterestParams remote_enable_request: RemoteEnableRequest remote_enable_result: RemoteEnableResult + remote_notify_steerable_changed_request: RemoteNotifySteerableChangedRequest + remote_notify_steerable_changed_result: RemoteNotifySteerableChangedResult remote_session_connection_result: RemoteSessionConnectionResult remote_session_mode: RemoteSessionMode + schedule_entry: ScheduleEntry + schedule_list: ScheduleList + schedule_stop_request: ScheduleStopRequest + schedule_stop_result: ScheduleStopResult + send_agent_mode: SendAgentMode + send_attachment: SendAttachment + send_attachment_blob: SendAttachmentBlob + send_attachment_directory: SendAttachmentDirectory + send_attachment_file: SendAttachmentFile + send_attachment_file_line_range: SendAttachmentFileLineRange + send_attachment_github_reference: SendAttachmentGithubReference + send_attachment_github_reference_type: SendAttachmentGithubReferenceTypeEnum + send_attachment_selection: SendAttachmentSelection + send_attachment_selection_details: SendAttachmentSelectionDetails + send_attachment_selection_details_end: SendAttachmentSelectionDetailsEnd + send_attachment_selection_details_start: SendAttachmentSelectionDetailsStart + send_mode: SendMode + send_request: SendRequest + send_result: SendResult server_skill: ServerSkill server_skill_list: ServerSkillList session_auth_status: SessionAuthStatus + session_bulk_delete_result: SessionBulkDeleteResult + session_context: SessionContext + session_context_host_type: SessionContextHostType + session_enrich_metadata_result: SessionEnrichMetadataResult session_fs_append_file_request: SessionFSAppendFileRequest session_fs_error: SessionFSError session_fs_error_code: SessionFSErrorCode @@ -7675,21 +14348,68 @@ class RPC: session_fs_stat_request: SessionFSStatRequest session_fs_stat_result: SessionFSStatResult session_fs_write_file_request: SessionFSWriteFileRequest + session_installed_plugin: SessionInstalledPlugin + session_installed_plugin_source: SessionInstalledPluginSource | str + session_installed_plugin_source_github: SessionInstalledPluginSourceGithub + session_installed_plugin_source_local: SessionInstalledPluginSourceLocal + session_installed_plugin_source_url: SessionInstalledPluginSourceURL + session_list: SessionList + session_load_deferred_repo_hooks_result: SessionLoadDeferredRepoHooksResult session_log_level: SessionLogLevel + session_metadata: SessionMetadata + session_metadata_snapshot: SessionMetadataSnapshot session_mode: SessionMode + session_prune_result: SessionPruneResult + sessions_bulk_delete_request: SessionsBulkDeleteRequest + sessions_check_in_use_request: SessionsCheckInUseRequest + sessions_check_in_use_result: SessionsCheckInUseResult + sessions_close_request: SessionsCloseRequest + sessions_close_result: SessionsCloseResult + sessions_enrich_metadata_request: SessionsEnrichMetadataRequest + session_set_credentials_params: SessionSetCredentialsParams + session_set_credentials_result: SessionSetCredentialsResult + sessions_find_by_prefix_request: SessionsFindByPrefixRequest + sessions_find_by_prefix_result: SessionsFindByPrefixResult + sessions_find_by_task_id_request: SessionsFindByTaskIDRequest + sessions_find_by_task_id_result: SessionsFindByTaskIDResult sessions_fork_request: SessionsForkRequest sessions_fork_result: SessionsForkResult + sessions_get_event_file_path_request: SessionsGetEventFilePathRequest + sessions_get_event_file_path_result: SessionsGetEventFilePathResult + sessions_get_last_for_context_request: SessionsGetLastForContextRequest + sessions_get_last_for_context_result: SessionsGetLastForContextResult + sessions_get_persisted_remote_steerable_request: SessionsGetPersistedRemoteSteerableRequest + sessions_get_persisted_remote_steerable_result: SessionsGetPersistedRemoteSteerableResult + session_sizes: SessionSizes + sessions_list_request: SessionsListRequest + sessions_load_deferred_repo_hooks_request: SessionsLoadDeferredRepoHooksRequest + sessions_prune_old_request: SessionsPruneOldRequest + sessions_release_lock_request: SessionsReleaseLockRequest + sessions_release_lock_result: SessionsReleaseLockResult + sessions_reload_plugin_hooks_request: SessionsReloadPluginHooksRequest + sessions_reload_plugin_hooks_result: SessionsReloadPluginHooksResult + sessions_save_request: SessionsSaveRequest + sessions_save_result: SessionsSaveResult + sessions_set_additional_plugins_request: SessionsSetAdditionalPluginsRequest + sessions_set_additional_plugins_result: SessionsSetAdditionalPluginsResult + session_update_options_params: SessionUpdateOptionsParams + session_update_options_result: SessionUpdateOptionsResult + session_working_directory_context: SessionWorkingDirectoryContext + session_working_directory_context_host_type: SessionContextHostType shell_exec_request: ShellExecRequest shell_exec_result: ShellExecResult shell_kill_request: ShellKillRequest shell_kill_result: ShellKillResult shell_kill_signal: ShellKillSignal + shutdown_request: ShutdownRequest skill: Skill skill_list: SkillList skills_config_set_disabled_skills_request: SkillsConfigSetDisabledSkillsRequest skills_disable_request: SkillsDisableRequest skills_discover_request: SkillsDiscoverRequest skills_enable_request: SkillsEnableRequest + skills_get_invoked_result: SkillsGetInvokedResult + skills_invoked_skill: SkillsInvokedSkill skills_load_diagnostics: SkillsLoadDiagnostics slash_command_agent_prompt_result: SlashCommandAgentPromptResult slash_command_completed_result: SlashCommandCompletedResult @@ -7700,15 +14420,22 @@ class RPC: slash_command_kind: SlashCommandKind slash_command_text_result: SlashCommandTextResult task_agent_info: TaskAgentInfo + task_agent_progress: TaskAgentProgress task_execution_mode: TaskExecutionMode task_info: TaskInfo task_list: TaskList tasks_cancel_request: TasksCancelRequest tasks_cancel_result: TasksCancelResult + tasks_get_current_promotable_result: TasksGetCurrentPromotableResult + tasks_get_progress_request: TasksGetProgressRequest + tasks_get_progress_result: TasksGetProgressResult task_shell_info: TaskShellInfo task_shell_info_attachment_mode: TaskShellInfoAttachmentMode + task_shell_progress: None + tasks_promote_current_to_background_result: TasksPromoteCurrentToBackgroundResult tasks_promote_to_background_request: TasksPromoteToBackgroundRequest tasks_promote_to_background_result: TasksPromoteToBackgroundResult + tasks_refresh_result: TasksRefreshResult tasks_remove_request: TasksRemoveRequest tasks_remove_result: TasksRemoveResult tasks_send_message_request: TasksSendMessageRequest @@ -7716,9 +14443,14 @@ class RPC: tasks_start_agent_request: TasksStartAgentRequest tasks_start_agent_result: TasksStartAgentResult task_status: TaskStatus + tasks_wait_for_pending_result: TasksWaitForPendingResult + telemetry_set_feature_overrides_request: TelemetrySetFeatureOverridesRequest + token_auth_info: TokenAuthInfo tool: Tool tool_list: ToolList + tools_initialize_and_validate_result: ToolsInitializeAndValidateResult tools_list_request: ToolsListRequest + ui_auto_mode_switch_response: UIAutoModeSwitchResponse ui_elicitation_array_any_of_field: UIElicitationArrayAnyOfField ui_elicitation_array_any_of_field_items: UIElicitationArrayAnyOfFieldItems ui_elicitation_array_any_of_field_items_any_of: UIElicitationArrayAnyOfFieldItemsAnyOf @@ -7740,7 +14472,19 @@ class RPC: ui_elicitation_string_enum_field: UIElicitationStringEnumField ui_elicitation_string_one_of_field: UIElicitationStringOneOfField ui_elicitation_string_one_of_field_one_of: UIElicitationStringOneOfFieldOneOf + ui_exit_plan_mode_action: UIExitPlanModeAction + ui_exit_plan_mode_response: UIExitPlanModeResponse + ui_handle_pending_auto_mode_switch_request: UIHandlePendingAutoModeSwitchRequest ui_handle_pending_elicitation_request: UIHandlePendingElicitationRequest + ui_handle_pending_exit_plan_mode_request: UIHandlePendingExitPlanModeRequest + ui_handle_pending_result: UIHandlePendingResult + ui_handle_pending_sampling_request: UIHandlePendingSamplingRequest + ui_handle_pending_sampling_response: dict[str, Any] + ui_handle_pending_user_input_request: UIHandlePendingUserInputRequest + ui_register_direct_auto_mode_switch_handler_result: UIRegisterDirectAutoModeSwitchHandlerResult + ui_unregister_direct_auto_mode_switch_handler_request: UIUnregisterDirectAutoModeSwitchHandlerRequest + ui_unregister_direct_auto_mode_switch_handler_result: UIUnregisterDirectAutoModeSwitchHandlerResult + ui_user_input_response: UIUserInputResponse usage_get_metrics_result: UsageGetMetricsResult usage_metrics_code_changes: UsageMetricsCodeChanges usage_metrics_model_metric: UsageMetricsModelMetric @@ -7748,24 +14492,47 @@ class RPC: usage_metrics_model_metric_token_detail: UsageMetricsModelMetricTokenDetail usage_metrics_model_metric_usage: UsageMetricsModelMetricUsage usage_metrics_token_detail: UsageMetricsTokenDetail + user_auth_info: UserAuthInfo + user_tool_session_approval_commands: UserToolSessionApprovalCommands + user_tool_session_approval_custom_tool: UserToolSessionApprovalCustomTool + user_tool_session_approval_extension_management: UserToolSessionApprovalExtensionManagement + user_tool_session_approval_extension_permission_access: UserToolSessionApprovalExtensionPermissionAccess + user_tool_session_approval_mcp: UserToolSessionApprovalMCP + user_tool_session_approval_memory: UserToolSessionApprovalMemory + user_tool_session_approval_read: UserToolSessionApprovalRead + user_tool_session_approval_write: UserToolSessionApprovalWrite + workspaces_checkpoints: WorkspacesCheckpoints workspaces_create_file_request: WorkspacesCreateFileRequest workspaces_get_workspace_result: WorkspacesGetWorkspaceResult + workspaces_list_checkpoints_result: WorkspacesListCheckpointsResult workspaces_list_files_result: WorkspacesListFilesResult + workspaces_read_checkpoint_request: WorkspacesReadCheckpointRequest + workspaces_read_checkpoint_result: WorkspacesReadCheckpointResult workspaces_read_file_request: WorkspacesReadFileRequest workspaces_read_file_result: WorkspacesReadFileResult + workspaces_save_large_paste_request: WorkspacesSaveLargePasteRequest + workspaces_save_large_paste_result: WorkspacesSaveLargePasteResult + session_context_info: SessionContextInfo | None = None + task_progress: TaskProgressClass | None = None + workspace_summary: WorkspaceSummary | None = None @staticmethod def from_dict(obj: Any) -> 'RPC': assert isinstance(obj, dict) + abort_request = AbortRequest.from_dict(obj.get("AbortRequest")) + abort_result = AbortResult.from_dict(obj.get("AbortResult")) account_get_quota_request = AccountGetQuotaRequest.from_dict(obj.get("AccountGetQuotaRequest")) account_get_quota_result = AccountGetQuotaResult.from_dict(obj.get("AccountGetQuotaResult")) account_quota_snapshot = AccountQuotaSnapshot.from_dict(obj.get("AccountQuotaSnapshot")) agent_get_current_result = AgentGetCurrentResult.from_dict(obj.get("AgentGetCurrentResult")) agent_info = AgentInfo.from_dict(obj.get("AgentInfo")) + agent_info_source = AgentInfoSource(obj.get("AgentInfoSource")) agent_list = AgentList.from_dict(obj.get("AgentList")) agent_reload_result = AgentReloadResult.from_dict(obj.get("AgentReloadResult")) agent_select_request = AgentSelectRequest.from_dict(obj.get("AgentSelectRequest")) agent_select_result = AgentSelectResult.from_dict(obj.get("AgentSelectResult")) + api_key_auth_info = APIKeyAuthInfo.from_dict(obj.get("ApiKeyAuthInfo")) + auth_info = AuthInfo.from_dict(obj.get("AuthInfo")) auth_info_type = AuthInfoType(obj.get("AuthInfoType")) command_list = CommandList.from_dict(obj.get("CommandList")) commands_handle_pending_command_request = CommandsHandlePendingCommandRequest.from_dict(obj.get("CommandsHandlePendingCommandRequest")) @@ -7781,9 +14548,28 @@ def from_dict(obj: Any) -> 'RPC': connect_request = ConnectRequest.from_dict(obj.get("ConnectRequest")) connect_result = ConnectResult.from_dict(obj.get("ConnectResult")) content_filter_mode = ContentFilterMode(obj.get("ContentFilterMode")) + copilot_api_token_auth_info = CopilotAPITokenAuthInfo.from_dict(obj.get("CopilotApiTokenAuthInfo")) + copilot_user_response = CopilotUserResponse.from_dict(obj.get("CopilotUserResponse")) + copilot_user_response_endpoints = CopilotUserResponseEndpoints.from_dict(obj.get("CopilotUserResponseEndpoints")) + copilot_user_response_quota_snapshots = from_dict(lambda x: from_union([CopilotUserResponseQuotaSnapshots.from_dict, from_none], x), obj.get("CopilotUserResponseQuotaSnapshots")) + copilot_user_response_quota_snapshots_chat = CopilotUserResponseQuotaSnapshotsChat.from_dict(obj.get("CopilotUserResponseQuotaSnapshotsChat")) + copilot_user_response_quota_snapshots_completions = CopilotUserResponseQuotaSnapshotsCompletions.from_dict(obj.get("CopilotUserResponseQuotaSnapshotsCompletions")) + copilot_user_response_quota_snapshots_premium_interactions = CopilotUserResponseQuotaSnapshotsPremiumInteractions.from_dict(obj.get("CopilotUserResponseQuotaSnapshotsPremiumInteractions")) current_model = CurrentModel.from_dict(obj.get("CurrentModel")) discovered_mcp_server = DiscoveredMCPServer.from_dict(obj.get("DiscoveredMcpServer")) discovered_mcp_server_type = DiscoveredMCPServerType(obj.get("DiscoveredMcpServerType")) + enqueue_command_params = EnqueueCommandParams.from_dict(obj.get("EnqueueCommandParams")) + enqueue_command_result = EnqueueCommandResult.from_dict(obj.get("EnqueueCommandResult")) + env_auth_info = EnvAuthInfo.from_dict(obj.get("EnvAuthInfo")) + event_log_read_request = EventLogReadRequest.from_dict(obj.get("EventLogReadRequest")) + event_log_release_interest_result = EventLogReleaseInterestResult.from_dict(obj.get("EventLogReleaseInterestResult")) + event_log_tail_result = EventLogTailResult.from_dict(obj.get("EventLogTailResult")) + event_log_types = from_union([lambda x: from_list(from_str, x), EventLogTypes], obj.get("EventLogTypes")) + events_agent_scope = EventsAgentScope(obj.get("EventsAgentScope")) + events_cursor_status = EventsCursorStatus(obj.get("EventsCursorStatus")) + events_read_result = EventsReadResult.from_dict(obj.get("EventsReadResult")) + execute_command_params = ExecuteCommandParams.from_dict(obj.get("ExecuteCommandParams")) + execute_command_result = ExecuteCommandResult.from_dict(obj.get("ExecuteCommandResult")) extension = Extension.from_dict(obj.get("Extension")) extension_list = ExtensionList.from_dict(obj.get("ExtensionList")) extensions_disable_request = ExtensionsDisableRequest.from_dict(obj.get("ExtensionsDisableRequest")) @@ -7807,18 +14593,31 @@ def from_dict(obj: Any) -> 'RPC': filter_mapping = from_union([lambda x: from_dict(ContentFilterMode, x), ContentFilterMode], obj.get("FilterMapping")) fleet_start_request = FleetStartRequest.from_dict(obj.get("FleetStartRequest")) fleet_start_result = FleetStartResult.from_dict(obj.get("FleetStartResult")) + gh_cli_auth_info = GhCLIAuthInfo.from_dict(obj.get("GhCliAuthInfo")) handle_pending_tool_call_request = HandlePendingToolCallRequest.from_dict(obj.get("HandlePendingToolCallRequest")) handle_pending_tool_call_result = HandlePendingToolCallResult.from_dict(obj.get("HandlePendingToolCallResult")) + history_abort_manual_compaction_result = HistoryAbortManualCompactionResult.from_dict(obj.get("HistoryAbortManualCompactionResult")) + history_cancel_background_compaction_result = HistoryCancelBackgroundCompactionResult.from_dict(obj.get("HistoryCancelBackgroundCompactionResult")) history_compact_context_window = HistoryCompactContextWindow.from_dict(obj.get("HistoryCompactContextWindow")) history_compact_result = HistoryCompactResult.from_dict(obj.get("HistoryCompactResult")) + history_summarize_for_handoff_result = HistorySummarizeForHandoffResult.from_dict(obj.get("HistorySummarizeForHandoffResult")) history_truncate_request = HistoryTruncateRequest.from_dict(obj.get("HistoryTruncateRequest")) history_truncate_result = HistoryTruncateResult.from_dict(obj.get("HistoryTruncateResult")) + hmac_auth_info = HMACAuthInfo.from_dict(obj.get("HMACAuthInfo")) + installed_plugin = InstalledPlugin.from_dict(obj.get("InstalledPlugin")) + installed_plugin_source = from_union([InstalledPluginSource.from_dict, from_str], obj.get("InstalledPluginSource")) + installed_plugin_source_github = InstalledPluginSourceGithub.from_dict(obj.get("InstalledPluginSourceGithub")) + installed_plugin_source_local = InstalledPluginSourceLocal.from_dict(obj.get("InstalledPluginSourceLocal")) + installed_plugin_source_url = InstalledPluginSourceURL.from_dict(obj.get("InstalledPluginSourceUrl")) instructions_get_sources_result = InstructionsGetSourcesResult.from_dict(obj.get("InstructionsGetSourcesResult")) instructions_sources = InstructionsSources.from_dict(obj.get("InstructionsSources")) instructions_sources_location = InstructionsSourcesLocation(obj.get("InstructionsSourcesLocation")) instructions_sources_type = InstructionsSourcesType(obj.get("InstructionsSourcesType")) log_request = LogRequest.from_dict(obj.get("LogRequest")) log_result = LogResult.from_dict(obj.get("LogResult")) + lsp_initialize_request = LspInitializeRequest.from_dict(obj.get("LspInitializeRequest")) + mcp_cancel_sampling_execution_params = MCPCancelSamplingExecutionParams.from_dict(obj.get("McpCancelSamplingExecutionParams")) + mcp_cancel_sampling_execution_result = MCPCancelSamplingExecutionResult.from_dict(obj.get("McpCancelSamplingExecutionResult")) mcp_config_add_request = MCPConfigAddRequest.from_dict(obj.get("McpConfigAddRequest")) mcp_config_disable_request = MCPConfigDisableRequest.from_dict(obj.get("McpConfigDisableRequest")) mcp_config_enable_request = MCPConfigEnableRequest.from_dict(obj.get("McpConfigEnableRequest")) @@ -7829,8 +14628,14 @@ def from_dict(obj: Any) -> 'RPC': mcp_discover_request = MCPDiscoverRequest.from_dict(obj.get("McpDiscoverRequest")) mcp_discover_result = MCPDiscoverResult.from_dict(obj.get("McpDiscoverResult")) mcp_enable_request = MCPEnableRequest.from_dict(obj.get("McpEnableRequest")) + mcp_execute_sampling_params = MCPExecuteSamplingParams.from_dict(obj.get("McpExecuteSamplingParams")) + mcp_execute_sampling_request = from_dict(lambda x: x, obj.get("McpExecuteSamplingRequest")) + mcp_execute_sampling_result = from_dict(lambda x: x, obj.get("McpExecuteSamplingResult")) mcp_oauth_login_request = MCPOauthLoginRequest.from_dict(obj.get("McpOauthLoginRequest")) mcp_oauth_login_result = MCPOauthLoginResult.from_dict(obj.get("McpOauthLoginResult")) + mcp_remove_git_hub_result = MCPRemoveGitHubResult.from_dict(obj.get("McpRemoveGitHubResult")) + mcp_sampling_execution_action = MCPSamplingExecutionAction(obj.get("McpSamplingExecutionAction")) + mcp_sampling_execution_result = MCPSamplingExecutionResult.from_dict(obj.get("McpSamplingExecutionResult")) mcp_server = MCPServer.from_dict(obj.get("McpServer")) mcp_server_config = MCPServerConfig.from_dict(obj.get("McpServerConfig")) mcp_server_config_http = MCPServerConfigHTTP.from_dict(obj.get("McpServerConfigHttp")) @@ -7839,6 +14644,22 @@ def from_dict(obj: Any) -> 'RPC': mcp_server_config_http_type = MCPServerConfigHTTPType(obj.get("McpServerConfigHttpType")) mcp_server_config_stdio = MCPServerConfigStdio.from_dict(obj.get("McpServerConfigStdio")) mcp_server_list = MCPServerList.from_dict(obj.get("McpServerList")) + mcp_set_env_value_mode_details = MCPSetEnvValueModeDetails(obj.get("McpSetEnvValueModeDetails")) + mcp_set_env_value_mode_params = MCPSetEnvValueModeParams.from_dict(obj.get("McpSetEnvValueModeParams")) + mcp_set_env_value_mode_result = MCPSetEnvValueModeResult.from_dict(obj.get("McpSetEnvValueModeResult")) + metadata_context_info_request = MetadataContextInfoRequest.from_dict(obj.get("MetadataContextInfoRequest")) + metadata_context_info_result = MetadataContextInfoResult.from_dict(obj.get("MetadataContextInfoResult")) + metadata_is_processing_result = MetadataIsProcessingResult.from_dict(obj.get("MetadataIsProcessingResult")) + metadata_recompute_context_tokens_request = MetadataRecomputeContextTokensRequest.from_dict(obj.get("MetadataRecomputeContextTokensRequest")) + metadata_recompute_context_tokens_result = MetadataRecomputeContextTokensResult.from_dict(obj.get("MetadataRecomputeContextTokensResult")) + metadata_record_context_change_request = MetadataRecordContextChangeRequest.from_dict(obj.get("MetadataRecordContextChangeRequest")) + metadata_record_context_change_result = MetadataRecordContextChangeResult.from_dict(obj.get("MetadataRecordContextChangeResult")) + metadata_set_working_directory_request = MetadataSetWorkingDirectoryRequest.from_dict(obj.get("MetadataSetWorkingDirectoryRequest")) + metadata_set_working_directory_result = MetadataSetWorkingDirectoryResult.from_dict(obj.get("MetadataSetWorkingDirectoryResult")) + metadata_snapshot_current_mode = MetadataSnapshotCurrentMode(obj.get("MetadataSnapshotCurrentMode")) + metadata_snapshot_remote_metadata = MetadataSnapshotRemoteMetadata.from_dict(obj.get("MetadataSnapshotRemoteMetadata")) + metadata_snapshot_remote_metadata_repository = MetadataSnapshotRemoteMetadataRepository.from_dict(obj.get("MetadataSnapshotRemoteMetadataRepository")) + metadata_snapshot_remote_metadata_task_type = MetadataSnapshotRemoteMetadataTaskType(obj.get("MetadataSnapshotRemoteMetadataTaskType")) model = Model.from_dict(obj.get("Model")) model_billing = ModelBilling.from_dict(obj.get("ModelBilling")) model_billing_token_prices = ModelBillingTokenPrices.from_dict(obj.get("ModelBillingTokenPrices")) @@ -7855,13 +14676,23 @@ def from_dict(obj: Any) -> 'RPC': model_picker_price_category = ModelPickerPriceCategory(obj.get("ModelPickerPriceCategory")) model_policy = ModelPolicy.from_dict(obj.get("ModelPolicy")) model_policy_state = ModelPolicyState(obj.get("ModelPolicyState")) + model_set_reasoning_effort_request = ModelSetReasoningEffortRequest.from_dict(obj.get("ModelSetReasoningEffortRequest")) + model_set_reasoning_effort_result = ModelSetReasoningEffortResult.from_dict(obj.get("ModelSetReasoningEffortResult")) models_list_request = ModelsListRequest.from_dict(obj.get("ModelsListRequest")) model_switch_to_request = ModelSwitchToRequest.from_dict(obj.get("ModelSwitchToRequest")) model_switch_to_result = ModelSwitchToResult.from_dict(obj.get("ModelSwitchToResult")) mode_set_request = ModeSetRequest.from_dict(obj.get("ModeSetRequest")) name_get_result = NameGetResult.from_dict(obj.get("NameGetResult")) + name_set_auto_request = NameSetAutoRequest.from_dict(obj.get("NameSetAutoRequest")) + name_set_auto_result = NameSetAutoResult.from_dict(obj.get("NameSetAutoResult")) name_set_request = NameSetRequest.from_dict(obj.get("NameSetRequest")) + options_update_env_value_mode = MCPSetEnvValueModeDetails(obj.get("OptionsUpdateEnvValueMode")) + pending_permission_request = PendingPermissionRequest.from_dict(obj.get("PendingPermissionRequest")) + pending_permission_request_list = PendingPermissionRequestList.from_dict(obj.get("PendingPermissionRequestList")) permission_decision = PermissionDecision.from_dict(obj.get("PermissionDecision")) + permission_decision_approved = PermissionDecisionApproved.from_dict(obj.get("PermissionDecisionApproved")) + permission_decision_approved_for_location = PermissionDecisionApprovedForLocation.from_dict(obj.get("PermissionDecisionApprovedForLocation")) + permission_decision_approved_for_session = PermissionDecisionApprovedForSession.from_dict(obj.get("PermissionDecisionApprovedForSession")) permission_decision_approve_for_location = PermissionDecisionApproveForLocation.from_dict(obj.get("PermissionDecisionApproveForLocation")) permission_decision_approve_for_location_approval = PermissionDecisionApproveForLocationApproval.from_dict(obj.get("PermissionDecisionApproveForLocationApproval")) permission_decision_approve_for_location_approval_commands = PermissionDecisionApproveForLocationApprovalCommands.from_dict(obj.get("PermissionDecisionApproveForLocationApprovalCommands")) @@ -7886,14 +14717,50 @@ def from_dict(obj: Any) -> 'RPC': permission_decision_approve_for_session_approval_write = PermissionDecisionApproveForSessionApprovalWrite.from_dict(obj.get("PermissionDecisionApproveForSessionApprovalWrite")) permission_decision_approve_once = PermissionDecisionApproveOnce.from_dict(obj.get("PermissionDecisionApproveOnce")) permission_decision_approve_permanently = PermissionDecisionApprovePermanently.from_dict(obj.get("PermissionDecisionApprovePermanently")) + permission_decision_cancelled = PermissionDecisionCancelled.from_dict(obj.get("PermissionDecisionCancelled")) + permission_decision_denied_by_content_exclusion_policy = PermissionDecisionDeniedByContentExclusionPolicy.from_dict(obj.get("PermissionDecisionDeniedByContentExclusionPolicy")) + permission_decision_denied_by_permission_request_hook = PermissionDecisionDeniedByPermissionRequestHook.from_dict(obj.get("PermissionDecisionDeniedByPermissionRequestHook")) + permission_decision_denied_by_rules = PermissionDecisionDeniedByRules.from_dict(obj.get("PermissionDecisionDeniedByRules")) + permission_decision_denied_interactively_by_user = PermissionDecisionDeniedInteractivelyByUser.from_dict(obj.get("PermissionDecisionDeniedInteractivelyByUser")) + permission_decision_denied_no_approval_rule_and_could_not_request_from_user = PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser.from_dict(obj.get("PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser")) permission_decision_reject = PermissionDecisionReject.from_dict(obj.get("PermissionDecisionReject")) permission_decision_request = PermissionDecisionRequest.from_dict(obj.get("PermissionDecisionRequest")) permission_decision_user_not_available = PermissionDecisionUserNotAvailable.from_dict(obj.get("PermissionDecisionUserNotAvailable")) + permission_paths_add_params = PermissionPathsAddParams.from_dict(obj.get("PermissionPathsAddParams")) + permission_paths_allowed_check_params = PermissionPathsAllowedCheckParams.from_dict(obj.get("PermissionPathsAllowedCheckParams")) + permission_paths_allowed_check_result = PermissionPathsAllowedCheckResult.from_dict(obj.get("PermissionPathsAllowedCheckResult")) + permission_paths_config = PermissionPathsConfig.from_dict(obj.get("PermissionPathsConfig")) + permission_paths_list = PermissionPathsList.from_dict(obj.get("PermissionPathsList")) + permission_paths_update_primary_params = PermissionPathsUpdatePrimaryParams.from_dict(obj.get("PermissionPathsUpdatePrimaryParams")) + permission_paths_workspace_check_params = PermissionPathsWorkspaceCheckParams.from_dict(obj.get("PermissionPathsWorkspaceCheckParams")) + permission_paths_workspace_check_result = PermissionPathsWorkspaceCheckResult.from_dict(obj.get("PermissionPathsWorkspaceCheckResult")) + permission_prompt_shown_notification = PermissionPromptShownNotification.from_dict(obj.get("PermissionPromptShownNotification")) permission_request_result = PermissionRequestResult.from_dict(obj.get("PermissionRequestResult")) + permission_rules_set = PermissionRulesSet.from_dict(obj.get("PermissionRulesSet")) + permissions_configure_additional_content_exclusion_policy = PermissionsConfigureAdditionalContentExclusionPolicy.from_dict(obj.get("PermissionsConfigureAdditionalContentExclusionPolicy")) + permissions_configure_additional_content_exclusion_policy_rule = PermissionsConfigureAdditionalContentExclusionPolicyRule.from_dict(obj.get("PermissionsConfigureAdditionalContentExclusionPolicyRule")) + permissions_configure_additional_content_exclusion_policy_rule_source = PermissionsConfigureAdditionalContentExclusionPolicyRuleSource.from_dict(obj.get("PermissionsConfigureAdditionalContentExclusionPolicyRuleSource")) + permissions_configure_additional_content_exclusion_policy_scope = PermissionsConfigureAdditionalContentExclusionPolicyScope(obj.get("PermissionsConfigureAdditionalContentExclusionPolicyScope")) + permissions_configure_params = PermissionsConfigureParams.from_dict(obj.get("PermissionsConfigureParams")) + permissions_configure_result = PermissionsConfigureResult.from_dict(obj.get("PermissionsConfigureResult")) + permissions_modify_rules_params = PermissionsModifyRulesParams.from_dict(obj.get("PermissionsModifyRulesParams")) + permissions_modify_rules_result = PermissionsModifyRulesResult.from_dict(obj.get("PermissionsModifyRulesResult")) + permissions_modify_rules_scope = PermissionsModifyRulesScope(obj.get("PermissionsModifyRulesScope")) + permissions_notify_prompt_shown_result = PermissionsNotifyPromptShownResult.from_dict(obj.get("PermissionsNotifyPromptShownResult")) + permissions_paths_add_result = PermissionsPathsAddResult.from_dict(obj.get("PermissionsPathsAddResult")) + permissions_paths_list_request = PermissionsPathsListRequest.from_dict(obj.get("PermissionsPathsListRequest")) + permissions_paths_update_primary_result = PermissionsPathsUpdatePrimaryResult.from_dict(obj.get("PermissionsPathsUpdatePrimaryResult")) + permissions_pending_requests_request = PermissionsPendingRequestsRequest.from_dict(obj.get("PermissionsPendingRequestsRequest")) permissions_reset_session_approvals_request = PermissionsResetSessionApprovalsRequest.from_dict(obj.get("PermissionsResetSessionApprovalsRequest")) permissions_reset_session_approvals_result = PermissionsResetSessionApprovalsResult.from_dict(obj.get("PermissionsResetSessionApprovalsResult")) permissions_set_approve_all_request = PermissionsSetApproveAllRequest.from_dict(obj.get("PermissionsSetApproveAllRequest")) permissions_set_approve_all_result = PermissionsSetApproveAllResult.from_dict(obj.get("PermissionsSetApproveAllResult")) + permissions_set_approve_all_source = PermissionsSetApproveAllSource(obj.get("PermissionsSetApproveAllSource")) + permissions_set_required_request = PermissionsSetRequiredRequest.from_dict(obj.get("PermissionsSetRequiredRequest")) + permissions_set_required_result = PermissionsSetRequiredResult.from_dict(obj.get("PermissionsSetRequiredResult")) + permissions_urls_set_unrestricted_mode_result = PermissionsUrlsSetUnrestrictedModeResult.from_dict(obj.get("PermissionsUrlsSetUnrestrictedModeResult")) + permission_urls_config = PermissionUrlsConfig.from_dict(obj.get("PermissionUrlsConfig")) + permission_urls_set_unrestricted_mode_params = PermissionUrlsSetUnrestrictedModeParams.from_dict(obj.get("PermissionUrlsSetUnrestrictedModeParams")) ping_request = PingRequest.from_dict(obj.get("PingRequest")) ping_result = PingResult.from_dict(obj.get("PingResult")) plan_read_result = PlanReadResult.from_dict(obj.get("PlanReadResult")) @@ -7903,13 +14770,45 @@ def from_dict(obj: Any) -> 'RPC': queued_command_handled = QueuedCommandHandled.from_dict(obj.get("QueuedCommandHandled")) queued_command_not_handled = QueuedCommandNotHandled.from_dict(obj.get("QueuedCommandNotHandled")) queued_command_result = QueuedCommandResult.from_dict(obj.get("QueuedCommandResult")) + queue_pending_items = QueuePendingItems.from_dict(obj.get("QueuePendingItems")) + queue_pending_items_kind = QueuePendingItemsKind(obj.get("QueuePendingItemsKind")) + queue_pending_items_result = QueuePendingItemsResult.from_dict(obj.get("QueuePendingItemsResult")) + queue_remove_most_recent_result = QueueRemoveMostRecentResult.from_dict(obj.get("QueueRemoveMostRecentResult")) + register_event_interest_params = RegisterEventInterestParams.from_dict(obj.get("RegisterEventInterestParams")) + register_event_interest_result = RegisterEventInterestResult.from_dict(obj.get("RegisterEventInterestResult")) + release_event_interest_params = ReleaseEventInterestParams.from_dict(obj.get("ReleaseEventInterestParams")) remote_enable_request = RemoteEnableRequest.from_dict(obj.get("RemoteEnableRequest")) remote_enable_result = RemoteEnableResult.from_dict(obj.get("RemoteEnableResult")) + remote_notify_steerable_changed_request = RemoteNotifySteerableChangedRequest.from_dict(obj.get("RemoteNotifySteerableChangedRequest")) + remote_notify_steerable_changed_result = RemoteNotifySteerableChangedResult.from_dict(obj.get("RemoteNotifySteerableChangedResult")) remote_session_connection_result = RemoteSessionConnectionResult.from_dict(obj.get("RemoteSessionConnectionResult")) remote_session_mode = RemoteSessionMode(obj.get("RemoteSessionMode")) + schedule_entry = ScheduleEntry.from_dict(obj.get("ScheduleEntry")) + schedule_list = ScheduleList.from_dict(obj.get("ScheduleList")) + schedule_stop_request = ScheduleStopRequest.from_dict(obj.get("ScheduleStopRequest")) + schedule_stop_result = ScheduleStopResult.from_dict(obj.get("ScheduleStopResult")) + send_agent_mode = SendAgentMode(obj.get("SendAgentMode")) + send_attachment = SendAttachment.from_dict(obj.get("SendAttachment")) + send_attachment_blob = SendAttachmentBlob.from_dict(obj.get("SendAttachmentBlob")) + send_attachment_directory = SendAttachmentDirectory.from_dict(obj.get("SendAttachmentDirectory")) + send_attachment_file = SendAttachmentFile.from_dict(obj.get("SendAttachmentFile")) + send_attachment_file_line_range = SendAttachmentFileLineRange.from_dict(obj.get("SendAttachmentFileLineRange")) + send_attachment_github_reference = SendAttachmentGithubReference.from_dict(obj.get("SendAttachmentGithubReference")) + send_attachment_github_reference_type = SendAttachmentGithubReferenceTypeEnum(obj.get("SendAttachmentGithubReferenceType")) + send_attachment_selection = SendAttachmentSelection.from_dict(obj.get("SendAttachmentSelection")) + send_attachment_selection_details = SendAttachmentSelectionDetails.from_dict(obj.get("SendAttachmentSelectionDetails")) + send_attachment_selection_details_end = SendAttachmentSelectionDetailsEnd.from_dict(obj.get("SendAttachmentSelectionDetailsEnd")) + send_attachment_selection_details_start = SendAttachmentSelectionDetailsStart.from_dict(obj.get("SendAttachmentSelectionDetailsStart")) + send_mode = SendMode(obj.get("SendMode")) + send_request = SendRequest.from_dict(obj.get("SendRequest")) + send_result = SendResult.from_dict(obj.get("SendResult")) server_skill = ServerSkill.from_dict(obj.get("ServerSkill")) server_skill_list = ServerSkillList.from_dict(obj.get("ServerSkillList")) session_auth_status = SessionAuthStatus.from_dict(obj.get("SessionAuthStatus")) + session_bulk_delete_result = SessionBulkDeleteResult.from_dict(obj.get("SessionBulkDeleteResult")) + session_context = SessionContext.from_dict(obj.get("SessionContext")) + session_context_host_type = SessionContextHostType(obj.get("SessionContextHostType")) + session_enrich_metadata_result = SessionEnrichMetadataResult.from_dict(obj.get("SessionEnrichMetadataResult")) session_fs_append_file_request = SessionFSAppendFileRequest.from_dict(obj.get("SessionFsAppendFileRequest")) session_fs_error = SessionFSError.from_dict(obj.get("SessionFsError")) session_fs_error_code = SessionFSErrorCode(obj.get("SessionFsErrorCode")) @@ -7938,21 +14837,68 @@ def from_dict(obj: Any) -> 'RPC': session_fs_stat_request = SessionFSStatRequest.from_dict(obj.get("SessionFsStatRequest")) session_fs_stat_result = SessionFSStatResult.from_dict(obj.get("SessionFsStatResult")) session_fs_write_file_request = SessionFSWriteFileRequest.from_dict(obj.get("SessionFsWriteFileRequest")) + session_installed_plugin = SessionInstalledPlugin.from_dict(obj.get("SessionInstalledPlugin")) + session_installed_plugin_source = from_union([SessionInstalledPluginSource.from_dict, from_str], obj.get("SessionInstalledPluginSource")) + session_installed_plugin_source_github = SessionInstalledPluginSourceGithub.from_dict(obj.get("SessionInstalledPluginSourceGithub")) + session_installed_plugin_source_local = SessionInstalledPluginSourceLocal.from_dict(obj.get("SessionInstalledPluginSourceLocal")) + session_installed_plugin_source_url = SessionInstalledPluginSourceURL.from_dict(obj.get("SessionInstalledPluginSourceUrl")) + session_list = SessionList.from_dict(obj.get("SessionList")) + session_load_deferred_repo_hooks_result = SessionLoadDeferredRepoHooksResult.from_dict(obj.get("SessionLoadDeferredRepoHooksResult")) session_log_level = SessionLogLevel(obj.get("SessionLogLevel")) + session_metadata = SessionMetadata.from_dict(obj.get("SessionMetadata")) + session_metadata_snapshot = SessionMetadataSnapshot.from_dict(obj.get("SessionMetadataSnapshot")) session_mode = SessionMode(obj.get("SessionMode")) + session_prune_result = SessionPruneResult.from_dict(obj.get("SessionPruneResult")) + sessions_bulk_delete_request = SessionsBulkDeleteRequest.from_dict(obj.get("SessionsBulkDeleteRequest")) + sessions_check_in_use_request = SessionsCheckInUseRequest.from_dict(obj.get("SessionsCheckInUseRequest")) + sessions_check_in_use_result = SessionsCheckInUseResult.from_dict(obj.get("SessionsCheckInUseResult")) + sessions_close_request = SessionsCloseRequest.from_dict(obj.get("SessionsCloseRequest")) + sessions_close_result = SessionsCloseResult.from_dict(obj.get("SessionsCloseResult")) + sessions_enrich_metadata_request = SessionsEnrichMetadataRequest.from_dict(obj.get("SessionsEnrichMetadataRequest")) + session_set_credentials_params = SessionSetCredentialsParams.from_dict(obj.get("SessionSetCredentialsParams")) + session_set_credentials_result = SessionSetCredentialsResult.from_dict(obj.get("SessionSetCredentialsResult")) + sessions_find_by_prefix_request = SessionsFindByPrefixRequest.from_dict(obj.get("SessionsFindByPrefixRequest")) + sessions_find_by_prefix_result = SessionsFindByPrefixResult.from_dict(obj.get("SessionsFindByPrefixResult")) + sessions_find_by_task_id_request = SessionsFindByTaskIDRequest.from_dict(obj.get("SessionsFindByTaskIDRequest")) + sessions_find_by_task_id_result = SessionsFindByTaskIDResult.from_dict(obj.get("SessionsFindByTaskIDResult")) sessions_fork_request = SessionsForkRequest.from_dict(obj.get("SessionsForkRequest")) sessions_fork_result = SessionsForkResult.from_dict(obj.get("SessionsForkResult")) + sessions_get_event_file_path_request = SessionsGetEventFilePathRequest.from_dict(obj.get("SessionsGetEventFilePathRequest")) + sessions_get_event_file_path_result = SessionsGetEventFilePathResult.from_dict(obj.get("SessionsGetEventFilePathResult")) + sessions_get_last_for_context_request = SessionsGetLastForContextRequest.from_dict(obj.get("SessionsGetLastForContextRequest")) + sessions_get_last_for_context_result = SessionsGetLastForContextResult.from_dict(obj.get("SessionsGetLastForContextResult")) + sessions_get_persisted_remote_steerable_request = SessionsGetPersistedRemoteSteerableRequest.from_dict(obj.get("SessionsGetPersistedRemoteSteerableRequest")) + sessions_get_persisted_remote_steerable_result = SessionsGetPersistedRemoteSteerableResult.from_dict(obj.get("SessionsGetPersistedRemoteSteerableResult")) + session_sizes = SessionSizes.from_dict(obj.get("SessionSizes")) + sessions_list_request = SessionsListRequest.from_dict(obj.get("SessionsListRequest")) + sessions_load_deferred_repo_hooks_request = SessionsLoadDeferredRepoHooksRequest.from_dict(obj.get("SessionsLoadDeferredRepoHooksRequest")) + sessions_prune_old_request = SessionsPruneOldRequest.from_dict(obj.get("SessionsPruneOldRequest")) + sessions_release_lock_request = SessionsReleaseLockRequest.from_dict(obj.get("SessionsReleaseLockRequest")) + sessions_release_lock_result = SessionsReleaseLockResult.from_dict(obj.get("SessionsReleaseLockResult")) + sessions_reload_plugin_hooks_request = SessionsReloadPluginHooksRequest.from_dict(obj.get("SessionsReloadPluginHooksRequest")) + sessions_reload_plugin_hooks_result = SessionsReloadPluginHooksResult.from_dict(obj.get("SessionsReloadPluginHooksResult")) + sessions_save_request = SessionsSaveRequest.from_dict(obj.get("SessionsSaveRequest")) + sessions_save_result = SessionsSaveResult.from_dict(obj.get("SessionsSaveResult")) + sessions_set_additional_plugins_request = SessionsSetAdditionalPluginsRequest.from_dict(obj.get("SessionsSetAdditionalPluginsRequest")) + sessions_set_additional_plugins_result = SessionsSetAdditionalPluginsResult.from_dict(obj.get("SessionsSetAdditionalPluginsResult")) + session_update_options_params = SessionUpdateOptionsParams.from_dict(obj.get("SessionUpdateOptionsParams")) + session_update_options_result = SessionUpdateOptionsResult.from_dict(obj.get("SessionUpdateOptionsResult")) + session_working_directory_context = SessionWorkingDirectoryContext.from_dict(obj.get("SessionWorkingDirectoryContext")) + session_working_directory_context_host_type = SessionContextHostType(obj.get("SessionWorkingDirectoryContextHostType")) shell_exec_request = ShellExecRequest.from_dict(obj.get("ShellExecRequest")) shell_exec_result = ShellExecResult.from_dict(obj.get("ShellExecResult")) shell_kill_request = ShellKillRequest.from_dict(obj.get("ShellKillRequest")) shell_kill_result = ShellKillResult.from_dict(obj.get("ShellKillResult")) shell_kill_signal = ShellKillSignal(obj.get("ShellKillSignal")) + shutdown_request = ShutdownRequest.from_dict(obj.get("ShutdownRequest")) skill = Skill.from_dict(obj.get("Skill")) skill_list = SkillList.from_dict(obj.get("SkillList")) skills_config_set_disabled_skills_request = SkillsConfigSetDisabledSkillsRequest.from_dict(obj.get("SkillsConfigSetDisabledSkillsRequest")) skills_disable_request = SkillsDisableRequest.from_dict(obj.get("SkillsDisableRequest")) skills_discover_request = SkillsDiscoverRequest.from_dict(obj.get("SkillsDiscoverRequest")) skills_enable_request = SkillsEnableRequest.from_dict(obj.get("SkillsEnableRequest")) + skills_get_invoked_result = SkillsGetInvokedResult.from_dict(obj.get("SkillsGetInvokedResult")) + skills_invoked_skill = SkillsInvokedSkill.from_dict(obj.get("SkillsInvokedSkill")) skills_load_diagnostics = SkillsLoadDiagnostics.from_dict(obj.get("SkillsLoadDiagnostics")) slash_command_agent_prompt_result = SlashCommandAgentPromptResult.from_dict(obj.get("SlashCommandAgentPromptResult")) slash_command_completed_result = SlashCommandCompletedResult.from_dict(obj.get("SlashCommandCompletedResult")) @@ -7963,15 +14909,22 @@ def from_dict(obj: Any) -> 'RPC': slash_command_kind = SlashCommandKind(obj.get("SlashCommandKind")) slash_command_text_result = SlashCommandTextResult.from_dict(obj.get("SlashCommandTextResult")) task_agent_info = TaskAgentInfo.from_dict(obj.get("TaskAgentInfo")) + task_agent_progress = TaskAgentProgress.from_dict(obj.get("TaskAgentProgress")) task_execution_mode = TaskExecutionMode(obj.get("TaskExecutionMode")) task_info = TaskInfo.from_dict(obj.get("TaskInfo")) task_list = TaskList.from_dict(obj.get("TaskList")) tasks_cancel_request = TasksCancelRequest.from_dict(obj.get("TasksCancelRequest")) tasks_cancel_result = TasksCancelResult.from_dict(obj.get("TasksCancelResult")) + tasks_get_current_promotable_result = TasksGetCurrentPromotableResult.from_dict(obj.get("TasksGetCurrentPromotableResult")) + tasks_get_progress_request = TasksGetProgressRequest.from_dict(obj.get("TasksGetProgressRequest")) + tasks_get_progress_result = TasksGetProgressResult.from_dict(obj.get("TasksGetProgressResult")) task_shell_info = TaskShellInfo.from_dict(obj.get("TaskShellInfo")) task_shell_info_attachment_mode = TaskShellInfoAttachmentMode(obj.get("TaskShellInfoAttachmentMode")) + task_shell_progress = from_none(obj.get("TaskShellProgress")) + tasks_promote_current_to_background_result = TasksPromoteCurrentToBackgroundResult.from_dict(obj.get("TasksPromoteCurrentToBackgroundResult")) tasks_promote_to_background_request = TasksPromoteToBackgroundRequest.from_dict(obj.get("TasksPromoteToBackgroundRequest")) tasks_promote_to_background_result = TasksPromoteToBackgroundResult.from_dict(obj.get("TasksPromoteToBackgroundResult")) + tasks_refresh_result = TasksRefreshResult.from_dict(obj.get("TasksRefreshResult")) tasks_remove_request = TasksRemoveRequest.from_dict(obj.get("TasksRemoveRequest")) tasks_remove_result = TasksRemoveResult.from_dict(obj.get("TasksRemoveResult")) tasks_send_message_request = TasksSendMessageRequest.from_dict(obj.get("TasksSendMessageRequest")) @@ -7979,9 +14932,14 @@ def from_dict(obj: Any) -> 'RPC': tasks_start_agent_request = TasksStartAgentRequest.from_dict(obj.get("TasksStartAgentRequest")) tasks_start_agent_result = TasksStartAgentResult.from_dict(obj.get("TasksStartAgentResult")) task_status = TaskStatus(obj.get("TaskStatus")) + tasks_wait_for_pending_result = TasksWaitForPendingResult.from_dict(obj.get("TasksWaitForPendingResult")) + telemetry_set_feature_overrides_request = TelemetrySetFeatureOverridesRequest.from_dict(obj.get("TelemetrySetFeatureOverridesRequest")) + token_auth_info = TokenAuthInfo.from_dict(obj.get("TokenAuthInfo")) tool = Tool.from_dict(obj.get("Tool")) tool_list = ToolList.from_dict(obj.get("ToolList")) + tools_initialize_and_validate_result = ToolsInitializeAndValidateResult.from_dict(obj.get("ToolsInitializeAndValidateResult")) tools_list_request = ToolsListRequest.from_dict(obj.get("ToolsListRequest")) + ui_auto_mode_switch_response = UIAutoModeSwitchResponse(obj.get("UIAutoModeSwitchResponse")) ui_elicitation_array_any_of_field = UIElicitationArrayAnyOfField.from_dict(obj.get("UIElicitationArrayAnyOfField")) ui_elicitation_array_any_of_field_items = UIElicitationArrayAnyOfFieldItems.from_dict(obj.get("UIElicitationArrayAnyOfFieldItems")) ui_elicitation_array_any_of_field_items_any_of = UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict(obj.get("UIElicitationArrayAnyOfFieldItemsAnyOf")) @@ -8003,7 +14961,19 @@ def from_dict(obj: Any) -> 'RPC': ui_elicitation_string_enum_field = UIElicitationStringEnumField.from_dict(obj.get("UIElicitationStringEnumField")) ui_elicitation_string_one_of_field = UIElicitationStringOneOfField.from_dict(obj.get("UIElicitationStringOneOfField")) ui_elicitation_string_one_of_field_one_of = UIElicitationStringOneOfFieldOneOf.from_dict(obj.get("UIElicitationStringOneOfFieldOneOf")) + ui_exit_plan_mode_action = UIExitPlanModeAction(obj.get("UIExitPlanModeAction")) + ui_exit_plan_mode_response = UIExitPlanModeResponse.from_dict(obj.get("UIExitPlanModeResponse")) + ui_handle_pending_auto_mode_switch_request = UIHandlePendingAutoModeSwitchRequest.from_dict(obj.get("UIHandlePendingAutoModeSwitchRequest")) ui_handle_pending_elicitation_request = UIHandlePendingElicitationRequest.from_dict(obj.get("UIHandlePendingElicitationRequest")) + ui_handle_pending_exit_plan_mode_request = UIHandlePendingExitPlanModeRequest.from_dict(obj.get("UIHandlePendingExitPlanModeRequest")) + ui_handle_pending_result = UIHandlePendingResult.from_dict(obj.get("UIHandlePendingResult")) + ui_handle_pending_sampling_request = UIHandlePendingSamplingRequest.from_dict(obj.get("UIHandlePendingSamplingRequest")) + ui_handle_pending_sampling_response = from_dict(lambda x: x, obj.get("UIHandlePendingSamplingResponse")) + ui_handle_pending_user_input_request = UIHandlePendingUserInputRequest.from_dict(obj.get("UIHandlePendingUserInputRequest")) + ui_register_direct_auto_mode_switch_handler_result = UIRegisterDirectAutoModeSwitchHandlerResult.from_dict(obj.get("UIRegisterDirectAutoModeSwitchHandlerResult")) + ui_unregister_direct_auto_mode_switch_handler_request = UIUnregisterDirectAutoModeSwitchHandlerRequest.from_dict(obj.get("UIUnregisterDirectAutoModeSwitchHandlerRequest")) + ui_unregister_direct_auto_mode_switch_handler_result = UIUnregisterDirectAutoModeSwitchHandlerResult.from_dict(obj.get("UIUnregisterDirectAutoModeSwitchHandlerResult")) + ui_user_input_response = UIUserInputResponse.from_dict(obj.get("UIUserInputResponse")) usage_get_metrics_result = UsageGetMetricsResult.from_dict(obj.get("UsageGetMetricsResult")) usage_metrics_code_changes = UsageMetricsCodeChanges.from_dict(obj.get("UsageMetricsCodeChanges")) usage_metrics_model_metric = UsageMetricsModelMetric.from_dict(obj.get("UsageMetricsModelMetric")) @@ -8011,24 +14981,47 @@ def from_dict(obj: Any) -> 'RPC': usage_metrics_model_metric_token_detail = UsageMetricsModelMetricTokenDetail.from_dict(obj.get("UsageMetricsModelMetricTokenDetail")) usage_metrics_model_metric_usage = UsageMetricsModelMetricUsage.from_dict(obj.get("UsageMetricsModelMetricUsage")) usage_metrics_token_detail = UsageMetricsTokenDetail.from_dict(obj.get("UsageMetricsTokenDetail")) + user_auth_info = UserAuthInfo.from_dict(obj.get("UserAuthInfo")) + user_tool_session_approval_commands = UserToolSessionApprovalCommands.from_dict(obj.get("UserToolSessionApprovalCommands")) + user_tool_session_approval_custom_tool = UserToolSessionApprovalCustomTool.from_dict(obj.get("UserToolSessionApprovalCustomTool")) + user_tool_session_approval_extension_management = UserToolSessionApprovalExtensionManagement.from_dict(obj.get("UserToolSessionApprovalExtensionManagement")) + user_tool_session_approval_extension_permission_access = UserToolSessionApprovalExtensionPermissionAccess.from_dict(obj.get("UserToolSessionApprovalExtensionPermissionAccess")) + user_tool_session_approval_mcp = UserToolSessionApprovalMCP.from_dict(obj.get("UserToolSessionApprovalMcp")) + user_tool_session_approval_memory = UserToolSessionApprovalMemory.from_dict(obj.get("UserToolSessionApprovalMemory")) + user_tool_session_approval_read = UserToolSessionApprovalRead.from_dict(obj.get("UserToolSessionApprovalRead")) + user_tool_session_approval_write = UserToolSessionApprovalWrite.from_dict(obj.get("UserToolSessionApprovalWrite")) + workspaces_checkpoints = WorkspacesCheckpoints.from_dict(obj.get("WorkspacesCheckpoints")) workspaces_create_file_request = WorkspacesCreateFileRequest.from_dict(obj.get("WorkspacesCreateFileRequest")) workspaces_get_workspace_result = WorkspacesGetWorkspaceResult.from_dict(obj.get("WorkspacesGetWorkspaceResult")) + workspaces_list_checkpoints_result = WorkspacesListCheckpointsResult.from_dict(obj.get("WorkspacesListCheckpointsResult")) workspaces_list_files_result = WorkspacesListFilesResult.from_dict(obj.get("WorkspacesListFilesResult")) + workspaces_read_checkpoint_request = WorkspacesReadCheckpointRequest.from_dict(obj.get("WorkspacesReadCheckpointRequest")) + workspaces_read_checkpoint_result = WorkspacesReadCheckpointResult.from_dict(obj.get("WorkspacesReadCheckpointResult")) workspaces_read_file_request = WorkspacesReadFileRequest.from_dict(obj.get("WorkspacesReadFileRequest")) workspaces_read_file_result = WorkspacesReadFileResult.from_dict(obj.get("WorkspacesReadFileResult")) - return RPC(account_get_quota_request, account_get_quota_result, account_quota_snapshot, agent_get_current_result, agent_info, agent_list, agent_reload_result, agent_select_request, agent_select_result, auth_info_type, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_filter_mode, current_model, discovered_mcp_server, discovered_mcp_server_type, extension, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, filter_mapping, fleet_start_request, fleet_start_result, handle_pending_tool_call_request, handle_pending_tool_call_result, history_compact_context_window, history_compact_result, history_truncate_request, history_truncate_result, instructions_get_sources_result, instructions_sources, instructions_sources_location, instructions_sources_type, log_request, log_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_oauth_login_request, mcp_oauth_login_result, mcp_server, mcp_server_config, mcp_server_config_http, mcp_server_config_http_auth, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_list, model, model_billing, model_billing_token_prices, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_picker_category, model_picker_price_category, model_policy, model_policy_state, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, name_get_result, name_set_request, permission_decision, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_reject, permission_decision_request, permission_decision_user_not_available, permission_request_result, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_approve_all_request, permissions_set_approve_all_result, ping_request, ping_result, plan_read_result, plan_update_request, plugin, plugin_list, queued_command_handled, queued_command_not_handled, queued_command_result, remote_enable_request, remote_enable_result, remote_session_connection_result, remote_session_mode, server_skill, server_skill_list, session_auth_status, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_log_level, session_mode, sessions_fork_request, sessions_fork_result, shell_exec_request, shell_exec_result, shell_kill_request, shell_kill_result, shell_kill_signal, skill, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_text_result, task_agent_info, task_execution_mode, task_info, task_list, tasks_cancel_request, tasks_cancel_result, task_shell_info, task_shell_info_attachment_mode, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tool, tool_list, tools_list_request, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_handle_pending_elicitation_request, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, workspaces_create_file_request, workspaces_get_workspace_result, workspaces_list_files_result, workspaces_read_file_request, workspaces_read_file_result) + workspaces_save_large_paste_request = WorkspacesSaveLargePasteRequest.from_dict(obj.get("WorkspacesSaveLargePasteRequest")) + workspaces_save_large_paste_result = WorkspacesSaveLargePasteResult.from_dict(obj.get("WorkspacesSaveLargePasteResult")) + session_context_info = from_union([SessionContextInfo.from_dict, from_none], obj.get("SessionContextInfo")) + task_progress = from_union([TaskProgressClass.from_dict, from_none], obj.get("TaskProgress")) + workspace_summary = from_union([WorkspaceSummary.from_dict, from_none], obj.get("WorkspaceSummary")) + return RPC(abort_request, abort_result, account_get_quota_request, account_get_quota_result, account_quota_snapshot, agent_get_current_result, agent_info, agent_info_source, agent_list, agent_reload_result, agent_select_request, agent_select_result, api_key_auth_info, auth_info, auth_info_type, command_list, commands_handle_pending_command_request, commands_handle_pending_command_result, commands_invoke_request, commands_list_request, commands_respond_to_queued_command_request, commands_respond_to_queued_command_result, connected_remote_session_metadata, connected_remote_session_metadata_kind, connected_remote_session_metadata_repository, connect_remote_session_params, connect_request, connect_result, content_filter_mode, copilot_api_token_auth_info, copilot_user_response, copilot_user_response_endpoints, copilot_user_response_quota_snapshots, copilot_user_response_quota_snapshots_chat, copilot_user_response_quota_snapshots_completions, copilot_user_response_quota_snapshots_premium_interactions, current_model, discovered_mcp_server, discovered_mcp_server_type, enqueue_command_params, enqueue_command_result, env_auth_info, event_log_read_request, event_log_release_interest_result, event_log_tail_result, event_log_types, events_agent_scope, events_cursor_status, events_read_result, execute_command_params, execute_command_result, extension, extension_list, extensions_disable_request, extensions_enable_request, extension_source, extension_status, external_tool_result, external_tool_text_result_for_llm, external_tool_text_result_for_llm_binary_results_for_llm, external_tool_text_result_for_llm_binary_results_for_llm_type, external_tool_text_result_for_llm_content, external_tool_text_result_for_llm_content_audio, external_tool_text_result_for_llm_content_image, external_tool_text_result_for_llm_content_resource, external_tool_text_result_for_llm_content_resource_details, external_tool_text_result_for_llm_content_resource_link, external_tool_text_result_for_llm_content_resource_link_icon, external_tool_text_result_for_llm_content_resource_link_icon_theme, external_tool_text_result_for_llm_content_terminal, external_tool_text_result_for_llm_content_text, filter_mapping, fleet_start_request, fleet_start_result, gh_cli_auth_info, handle_pending_tool_call_request, handle_pending_tool_call_result, history_abort_manual_compaction_result, history_cancel_background_compaction_result, history_compact_context_window, history_compact_result, history_summarize_for_handoff_result, history_truncate_request, history_truncate_result, hmac_auth_info, installed_plugin, installed_plugin_source, installed_plugin_source_github, installed_plugin_source_local, installed_plugin_source_url, instructions_get_sources_result, instructions_sources, instructions_sources_location, instructions_sources_type, log_request, log_result, lsp_initialize_request, mcp_cancel_sampling_execution_params, mcp_cancel_sampling_execution_result, mcp_config_add_request, mcp_config_disable_request, mcp_config_enable_request, mcp_config_list, mcp_config_remove_request, mcp_config_update_request, mcp_disable_request, mcp_discover_request, mcp_discover_result, mcp_enable_request, mcp_execute_sampling_params, mcp_execute_sampling_request, mcp_execute_sampling_result, mcp_oauth_login_request, mcp_oauth_login_result, mcp_remove_git_hub_result, mcp_sampling_execution_action, mcp_sampling_execution_result, mcp_server, mcp_server_config, mcp_server_config_http, mcp_server_config_http_auth, mcp_server_config_http_oauth_grant_type, mcp_server_config_http_type, mcp_server_config_stdio, mcp_server_list, mcp_set_env_value_mode_details, mcp_set_env_value_mode_params, mcp_set_env_value_mode_result, metadata_context_info_request, metadata_context_info_result, metadata_is_processing_result, metadata_recompute_context_tokens_request, metadata_recompute_context_tokens_result, metadata_record_context_change_request, metadata_record_context_change_result, metadata_set_working_directory_request, metadata_set_working_directory_result, metadata_snapshot_current_mode, metadata_snapshot_remote_metadata, metadata_snapshot_remote_metadata_repository, metadata_snapshot_remote_metadata_task_type, model, model_billing, model_billing_token_prices, model_capabilities, model_capabilities_limits, model_capabilities_limits_vision, model_capabilities_override, model_capabilities_override_limits, model_capabilities_override_limits_vision, model_capabilities_override_supports, model_capabilities_supports, model_list, model_picker_category, model_picker_price_category, model_policy, model_policy_state, model_set_reasoning_effort_request, model_set_reasoning_effort_result, models_list_request, model_switch_to_request, model_switch_to_result, mode_set_request, name_get_result, name_set_auto_request, name_set_auto_result, name_set_request, options_update_env_value_mode, pending_permission_request, pending_permission_request_list, permission_decision, permission_decision_approved, permission_decision_approved_for_location, permission_decision_approved_for_session, permission_decision_approve_for_location, permission_decision_approve_for_location_approval, permission_decision_approve_for_location_approval_commands, permission_decision_approve_for_location_approval_custom_tool, permission_decision_approve_for_location_approval_extension_management, permission_decision_approve_for_location_approval_extension_permission_access, permission_decision_approve_for_location_approval_mcp, permission_decision_approve_for_location_approval_mcp_sampling, permission_decision_approve_for_location_approval_memory, permission_decision_approve_for_location_approval_read, permission_decision_approve_for_location_approval_write, permission_decision_approve_for_session, permission_decision_approve_for_session_approval, permission_decision_approve_for_session_approval_commands, permission_decision_approve_for_session_approval_custom_tool, permission_decision_approve_for_session_approval_extension_management, permission_decision_approve_for_session_approval_extension_permission_access, permission_decision_approve_for_session_approval_mcp, permission_decision_approve_for_session_approval_mcp_sampling, permission_decision_approve_for_session_approval_memory, permission_decision_approve_for_session_approval_read, permission_decision_approve_for_session_approval_write, permission_decision_approve_once, permission_decision_approve_permanently, permission_decision_cancelled, permission_decision_denied_by_content_exclusion_policy, permission_decision_denied_by_permission_request_hook, permission_decision_denied_by_rules, permission_decision_denied_interactively_by_user, permission_decision_denied_no_approval_rule_and_could_not_request_from_user, permission_decision_reject, permission_decision_request, permission_decision_user_not_available, permission_paths_add_params, permission_paths_allowed_check_params, permission_paths_allowed_check_result, permission_paths_config, permission_paths_list, permission_paths_update_primary_params, permission_paths_workspace_check_params, permission_paths_workspace_check_result, permission_prompt_shown_notification, permission_request_result, permission_rules_set, permissions_configure_additional_content_exclusion_policy, permissions_configure_additional_content_exclusion_policy_rule, permissions_configure_additional_content_exclusion_policy_rule_source, permissions_configure_additional_content_exclusion_policy_scope, permissions_configure_params, permissions_configure_result, permissions_modify_rules_params, permissions_modify_rules_result, permissions_modify_rules_scope, permissions_notify_prompt_shown_result, permissions_paths_add_result, permissions_paths_list_request, permissions_paths_update_primary_result, permissions_pending_requests_request, permissions_reset_session_approvals_request, permissions_reset_session_approvals_result, permissions_set_approve_all_request, permissions_set_approve_all_result, permissions_set_approve_all_source, permissions_set_required_request, permissions_set_required_result, permissions_urls_set_unrestricted_mode_result, permission_urls_config, permission_urls_set_unrestricted_mode_params, ping_request, ping_result, plan_read_result, plan_update_request, plugin, plugin_list, queued_command_handled, queued_command_not_handled, queued_command_result, queue_pending_items, queue_pending_items_kind, queue_pending_items_result, queue_remove_most_recent_result, register_event_interest_params, register_event_interest_result, release_event_interest_params, remote_enable_request, remote_enable_result, remote_notify_steerable_changed_request, remote_notify_steerable_changed_result, remote_session_connection_result, remote_session_mode, schedule_entry, schedule_list, schedule_stop_request, schedule_stop_result, send_agent_mode, send_attachment, send_attachment_blob, send_attachment_directory, send_attachment_file, send_attachment_file_line_range, send_attachment_github_reference, send_attachment_github_reference_type, send_attachment_selection, send_attachment_selection_details, send_attachment_selection_details_end, send_attachment_selection_details_start, send_mode, send_request, send_result, server_skill, server_skill_list, session_auth_status, session_bulk_delete_result, session_context, session_context_host_type, session_enrich_metadata_result, session_fs_append_file_request, session_fs_error, session_fs_error_code, session_fs_exists_request, session_fs_exists_result, session_fs_mkdir_request, session_fs_readdir_request, session_fs_readdir_result, session_fs_readdir_with_types_entry, session_fs_readdir_with_types_entry_type, session_fs_readdir_with_types_request, session_fs_readdir_with_types_result, session_fs_read_file_request, session_fs_read_file_result, session_fs_rename_request, session_fs_rm_request, session_fs_set_provider_capabilities, session_fs_set_provider_conventions, session_fs_set_provider_request, session_fs_set_provider_result, session_fs_sqlite_exists_request, session_fs_sqlite_exists_result, session_fs_sqlite_query_request, session_fs_sqlite_query_result, session_fs_sqlite_query_type, session_fs_stat_request, session_fs_stat_result, session_fs_write_file_request, session_installed_plugin, session_installed_plugin_source, session_installed_plugin_source_github, session_installed_plugin_source_local, session_installed_plugin_source_url, session_list, session_load_deferred_repo_hooks_result, session_log_level, session_metadata, session_metadata_snapshot, session_mode, session_prune_result, sessions_bulk_delete_request, sessions_check_in_use_request, sessions_check_in_use_result, sessions_close_request, sessions_close_result, sessions_enrich_metadata_request, session_set_credentials_params, session_set_credentials_result, sessions_find_by_prefix_request, sessions_find_by_prefix_result, sessions_find_by_task_id_request, sessions_find_by_task_id_result, sessions_fork_request, sessions_fork_result, sessions_get_event_file_path_request, sessions_get_event_file_path_result, sessions_get_last_for_context_request, sessions_get_last_for_context_result, sessions_get_persisted_remote_steerable_request, sessions_get_persisted_remote_steerable_result, session_sizes, sessions_list_request, sessions_load_deferred_repo_hooks_request, sessions_prune_old_request, sessions_release_lock_request, sessions_release_lock_result, sessions_reload_plugin_hooks_request, sessions_reload_plugin_hooks_result, sessions_save_request, sessions_save_result, sessions_set_additional_plugins_request, sessions_set_additional_plugins_result, session_update_options_params, session_update_options_result, session_working_directory_context, session_working_directory_context_host_type, shell_exec_request, shell_exec_result, shell_kill_request, shell_kill_result, shell_kill_signal, shutdown_request, skill, skill_list, skills_config_set_disabled_skills_request, skills_disable_request, skills_discover_request, skills_enable_request, skills_get_invoked_result, skills_invoked_skill, skills_load_diagnostics, slash_command_agent_prompt_result, slash_command_completed_result, slash_command_info, slash_command_input, slash_command_input_completion, slash_command_invocation_result, slash_command_kind, slash_command_text_result, task_agent_info, task_agent_progress, task_execution_mode, task_info, task_list, tasks_cancel_request, tasks_cancel_result, tasks_get_current_promotable_result, tasks_get_progress_request, tasks_get_progress_result, task_shell_info, task_shell_info_attachment_mode, task_shell_progress, tasks_promote_current_to_background_result, tasks_promote_to_background_request, tasks_promote_to_background_result, tasks_refresh_result, tasks_remove_request, tasks_remove_result, tasks_send_message_request, tasks_send_message_result, tasks_start_agent_request, tasks_start_agent_result, task_status, tasks_wait_for_pending_result, telemetry_set_feature_overrides_request, token_auth_info, tool, tool_list, tools_initialize_and_validate_result, tools_list_request, ui_auto_mode_switch_response, ui_elicitation_array_any_of_field, ui_elicitation_array_any_of_field_items, ui_elicitation_array_any_of_field_items_any_of, ui_elicitation_array_enum_field, ui_elicitation_array_enum_field_items, ui_elicitation_field_value, ui_elicitation_request, ui_elicitation_response, ui_elicitation_response_action, ui_elicitation_response_content, ui_elicitation_result, ui_elicitation_schema, ui_elicitation_schema_property, ui_elicitation_schema_property_boolean, ui_elicitation_schema_property_number, ui_elicitation_schema_property_number_type, ui_elicitation_schema_property_string, ui_elicitation_schema_property_string_format, ui_elicitation_string_enum_field, ui_elicitation_string_one_of_field, ui_elicitation_string_one_of_field_one_of, ui_exit_plan_mode_action, ui_exit_plan_mode_response, ui_handle_pending_auto_mode_switch_request, ui_handle_pending_elicitation_request, ui_handle_pending_exit_plan_mode_request, ui_handle_pending_result, ui_handle_pending_sampling_request, ui_handle_pending_sampling_response, ui_handle_pending_user_input_request, ui_register_direct_auto_mode_switch_handler_result, ui_unregister_direct_auto_mode_switch_handler_request, ui_unregister_direct_auto_mode_switch_handler_result, ui_user_input_response, usage_get_metrics_result, usage_metrics_code_changes, usage_metrics_model_metric, usage_metrics_model_metric_requests, usage_metrics_model_metric_token_detail, usage_metrics_model_metric_usage, usage_metrics_token_detail, user_auth_info, user_tool_session_approval_commands, user_tool_session_approval_custom_tool, user_tool_session_approval_extension_management, user_tool_session_approval_extension_permission_access, user_tool_session_approval_mcp, user_tool_session_approval_memory, user_tool_session_approval_read, user_tool_session_approval_write, workspaces_checkpoints, workspaces_create_file_request, workspaces_get_workspace_result, workspaces_list_checkpoints_result, workspaces_list_files_result, workspaces_read_checkpoint_request, workspaces_read_checkpoint_result, workspaces_read_file_request, workspaces_read_file_result, workspaces_save_large_paste_request, workspaces_save_large_paste_result, session_context_info, task_progress, workspace_summary) def to_dict(self) -> dict: result: dict = {} + result["AbortRequest"] = to_class(AbortRequest, self.abort_request) + result["AbortResult"] = to_class(AbortResult, self.abort_result) result["AccountGetQuotaRequest"] = to_class(AccountGetQuotaRequest, self.account_get_quota_request) result["AccountGetQuotaResult"] = to_class(AccountGetQuotaResult, self.account_get_quota_result) result["AccountQuotaSnapshot"] = to_class(AccountQuotaSnapshot, self.account_quota_snapshot) result["AgentGetCurrentResult"] = to_class(AgentGetCurrentResult, self.agent_get_current_result) result["AgentInfo"] = to_class(AgentInfo, self.agent_info) + result["AgentInfoSource"] = to_enum(AgentInfoSource, self.agent_info_source) result["AgentList"] = to_class(AgentList, self.agent_list) result["AgentReloadResult"] = to_class(AgentReloadResult, self.agent_reload_result) result["AgentSelectRequest"] = to_class(AgentSelectRequest, self.agent_select_request) result["AgentSelectResult"] = to_class(AgentSelectResult, self.agent_select_result) + result["ApiKeyAuthInfo"] = to_class(APIKeyAuthInfo, self.api_key_auth_info) + result["AuthInfo"] = to_class(AuthInfo, self.auth_info) result["AuthInfoType"] = to_enum(AuthInfoType, self.auth_info_type) result["CommandList"] = to_class(CommandList, self.command_list) result["CommandsHandlePendingCommandRequest"] = to_class(CommandsHandlePendingCommandRequest, self.commands_handle_pending_command_request) @@ -8044,9 +15037,28 @@ def to_dict(self) -> dict: result["ConnectRequest"] = to_class(ConnectRequest, self.connect_request) result["ConnectResult"] = to_class(ConnectResult, self.connect_result) result["ContentFilterMode"] = to_enum(ContentFilterMode, self.content_filter_mode) + result["CopilotApiTokenAuthInfo"] = to_class(CopilotAPITokenAuthInfo, self.copilot_api_token_auth_info) + result["CopilotUserResponse"] = to_class(CopilotUserResponse, self.copilot_user_response) + result["CopilotUserResponseEndpoints"] = to_class(CopilotUserResponseEndpoints, self.copilot_user_response_endpoints) + result["CopilotUserResponseQuotaSnapshots"] = from_dict(lambda x: from_union([lambda x: to_class(CopilotUserResponseQuotaSnapshots, x), from_none], x), self.copilot_user_response_quota_snapshots) + result["CopilotUserResponseQuotaSnapshotsChat"] = to_class(CopilotUserResponseQuotaSnapshotsChat, self.copilot_user_response_quota_snapshots_chat) + result["CopilotUserResponseQuotaSnapshotsCompletions"] = to_class(CopilotUserResponseQuotaSnapshotsCompletions, self.copilot_user_response_quota_snapshots_completions) + result["CopilotUserResponseQuotaSnapshotsPremiumInteractions"] = to_class(CopilotUserResponseQuotaSnapshotsPremiumInteractions, self.copilot_user_response_quota_snapshots_premium_interactions) result["CurrentModel"] = to_class(CurrentModel, self.current_model) result["DiscoveredMcpServer"] = to_class(DiscoveredMCPServer, self.discovered_mcp_server) result["DiscoveredMcpServerType"] = to_enum(DiscoveredMCPServerType, self.discovered_mcp_server_type) + result["EnqueueCommandParams"] = to_class(EnqueueCommandParams, self.enqueue_command_params) + result["EnqueueCommandResult"] = to_class(EnqueueCommandResult, self.enqueue_command_result) + result["EnvAuthInfo"] = to_class(EnvAuthInfo, self.env_auth_info) + result["EventLogReadRequest"] = to_class(EventLogReadRequest, self.event_log_read_request) + result["EventLogReleaseInterestResult"] = to_class(EventLogReleaseInterestResult, self.event_log_release_interest_result) + result["EventLogTailResult"] = to_class(EventLogTailResult, self.event_log_tail_result) + result["EventLogTypes"] = from_union([lambda x: from_list(from_str, x), lambda x: to_enum(EventLogTypes, x)], self.event_log_types) + result["EventsAgentScope"] = to_enum(EventsAgentScope, self.events_agent_scope) + result["EventsCursorStatus"] = to_enum(EventsCursorStatus, self.events_cursor_status) + result["EventsReadResult"] = to_class(EventsReadResult, self.events_read_result) + result["ExecuteCommandParams"] = to_class(ExecuteCommandParams, self.execute_command_params) + result["ExecuteCommandResult"] = to_class(ExecuteCommandResult, self.execute_command_result) result["Extension"] = to_class(Extension, self.extension) result["ExtensionList"] = to_class(ExtensionList, self.extension_list) result["ExtensionsDisableRequest"] = to_class(ExtensionsDisableRequest, self.extensions_disable_request) @@ -8070,18 +15082,31 @@ def to_dict(self) -> dict: result["FilterMapping"] = from_union([lambda x: from_dict(lambda x: to_enum(ContentFilterMode, x), x), lambda x: to_enum(ContentFilterMode, x)], self.filter_mapping) result["FleetStartRequest"] = to_class(FleetStartRequest, self.fleet_start_request) result["FleetStartResult"] = to_class(FleetStartResult, self.fleet_start_result) + result["GhCliAuthInfo"] = to_class(GhCLIAuthInfo, self.gh_cli_auth_info) result["HandlePendingToolCallRequest"] = to_class(HandlePendingToolCallRequest, self.handle_pending_tool_call_request) result["HandlePendingToolCallResult"] = to_class(HandlePendingToolCallResult, self.handle_pending_tool_call_result) + result["HistoryAbortManualCompactionResult"] = to_class(HistoryAbortManualCompactionResult, self.history_abort_manual_compaction_result) + result["HistoryCancelBackgroundCompactionResult"] = to_class(HistoryCancelBackgroundCompactionResult, self.history_cancel_background_compaction_result) result["HistoryCompactContextWindow"] = to_class(HistoryCompactContextWindow, self.history_compact_context_window) result["HistoryCompactResult"] = to_class(HistoryCompactResult, self.history_compact_result) + result["HistorySummarizeForHandoffResult"] = to_class(HistorySummarizeForHandoffResult, self.history_summarize_for_handoff_result) result["HistoryTruncateRequest"] = to_class(HistoryTruncateRequest, self.history_truncate_request) result["HistoryTruncateResult"] = to_class(HistoryTruncateResult, self.history_truncate_result) + result["HMACAuthInfo"] = to_class(HMACAuthInfo, self.hmac_auth_info) + result["InstalledPlugin"] = to_class(InstalledPlugin, self.installed_plugin) + result["InstalledPluginSource"] = from_union([lambda x: to_class(InstalledPluginSource, x), from_str], self.installed_plugin_source) + result["InstalledPluginSourceGithub"] = to_class(InstalledPluginSourceGithub, self.installed_plugin_source_github) + result["InstalledPluginSourceLocal"] = to_class(InstalledPluginSourceLocal, self.installed_plugin_source_local) + result["InstalledPluginSourceUrl"] = to_class(InstalledPluginSourceURL, self.installed_plugin_source_url) result["InstructionsGetSourcesResult"] = to_class(InstructionsGetSourcesResult, self.instructions_get_sources_result) result["InstructionsSources"] = to_class(InstructionsSources, self.instructions_sources) result["InstructionsSourcesLocation"] = to_enum(InstructionsSourcesLocation, self.instructions_sources_location) result["InstructionsSourcesType"] = to_enum(InstructionsSourcesType, self.instructions_sources_type) result["LogRequest"] = to_class(LogRequest, self.log_request) result["LogResult"] = to_class(LogResult, self.log_result) + result["LspInitializeRequest"] = to_class(LspInitializeRequest, self.lsp_initialize_request) + result["McpCancelSamplingExecutionParams"] = to_class(MCPCancelSamplingExecutionParams, self.mcp_cancel_sampling_execution_params) + result["McpCancelSamplingExecutionResult"] = to_class(MCPCancelSamplingExecutionResult, self.mcp_cancel_sampling_execution_result) result["McpConfigAddRequest"] = to_class(MCPConfigAddRequest, self.mcp_config_add_request) result["McpConfigDisableRequest"] = to_class(MCPConfigDisableRequest, self.mcp_config_disable_request) result["McpConfigEnableRequest"] = to_class(MCPConfigEnableRequest, self.mcp_config_enable_request) @@ -8092,8 +15117,14 @@ def to_dict(self) -> dict: result["McpDiscoverRequest"] = to_class(MCPDiscoverRequest, self.mcp_discover_request) result["McpDiscoverResult"] = to_class(MCPDiscoverResult, self.mcp_discover_result) result["McpEnableRequest"] = to_class(MCPEnableRequest, self.mcp_enable_request) + result["McpExecuteSamplingParams"] = to_class(MCPExecuteSamplingParams, self.mcp_execute_sampling_params) + result["McpExecuteSamplingRequest"] = from_dict(lambda x: x, self.mcp_execute_sampling_request) + result["McpExecuteSamplingResult"] = from_dict(lambda x: x, self.mcp_execute_sampling_result) result["McpOauthLoginRequest"] = to_class(MCPOauthLoginRequest, self.mcp_oauth_login_request) result["McpOauthLoginResult"] = to_class(MCPOauthLoginResult, self.mcp_oauth_login_result) + result["McpRemoveGitHubResult"] = to_class(MCPRemoveGitHubResult, self.mcp_remove_git_hub_result) + result["McpSamplingExecutionAction"] = to_enum(MCPSamplingExecutionAction, self.mcp_sampling_execution_action) + result["McpSamplingExecutionResult"] = to_class(MCPSamplingExecutionResult, self.mcp_sampling_execution_result) result["McpServer"] = to_class(MCPServer, self.mcp_server) result["McpServerConfig"] = to_class(MCPServerConfig, self.mcp_server_config) result["McpServerConfigHttp"] = to_class(MCPServerConfigHTTP, self.mcp_server_config_http) @@ -8102,6 +15133,22 @@ def to_dict(self) -> dict: result["McpServerConfigHttpType"] = to_enum(MCPServerConfigHTTPType, self.mcp_server_config_http_type) result["McpServerConfigStdio"] = to_class(MCPServerConfigStdio, self.mcp_server_config_stdio) result["McpServerList"] = to_class(MCPServerList, self.mcp_server_list) + result["McpSetEnvValueModeDetails"] = to_enum(MCPSetEnvValueModeDetails, self.mcp_set_env_value_mode_details) + result["McpSetEnvValueModeParams"] = to_class(MCPSetEnvValueModeParams, self.mcp_set_env_value_mode_params) + result["McpSetEnvValueModeResult"] = to_class(MCPSetEnvValueModeResult, self.mcp_set_env_value_mode_result) + result["MetadataContextInfoRequest"] = to_class(MetadataContextInfoRequest, self.metadata_context_info_request) + result["MetadataContextInfoResult"] = to_class(MetadataContextInfoResult, self.metadata_context_info_result) + result["MetadataIsProcessingResult"] = to_class(MetadataIsProcessingResult, self.metadata_is_processing_result) + result["MetadataRecomputeContextTokensRequest"] = to_class(MetadataRecomputeContextTokensRequest, self.metadata_recompute_context_tokens_request) + result["MetadataRecomputeContextTokensResult"] = to_class(MetadataRecomputeContextTokensResult, self.metadata_recompute_context_tokens_result) + result["MetadataRecordContextChangeRequest"] = to_class(MetadataRecordContextChangeRequest, self.metadata_record_context_change_request) + result["MetadataRecordContextChangeResult"] = to_class(MetadataRecordContextChangeResult, self.metadata_record_context_change_result) + result["MetadataSetWorkingDirectoryRequest"] = to_class(MetadataSetWorkingDirectoryRequest, self.metadata_set_working_directory_request) + result["MetadataSetWorkingDirectoryResult"] = to_class(MetadataSetWorkingDirectoryResult, self.metadata_set_working_directory_result) + result["MetadataSnapshotCurrentMode"] = to_enum(MetadataSnapshotCurrentMode, self.metadata_snapshot_current_mode) + result["MetadataSnapshotRemoteMetadata"] = to_class(MetadataSnapshotRemoteMetadata, self.metadata_snapshot_remote_metadata) + result["MetadataSnapshotRemoteMetadataRepository"] = to_class(MetadataSnapshotRemoteMetadataRepository, self.metadata_snapshot_remote_metadata_repository) + result["MetadataSnapshotRemoteMetadataTaskType"] = to_enum(MetadataSnapshotRemoteMetadataTaskType, self.metadata_snapshot_remote_metadata_task_type) result["Model"] = to_class(Model, self.model) result["ModelBilling"] = to_class(ModelBilling, self.model_billing) result["ModelBillingTokenPrices"] = to_class(ModelBillingTokenPrices, self.model_billing_token_prices) @@ -8118,13 +15165,23 @@ def to_dict(self) -> dict: result["ModelPickerPriceCategory"] = to_enum(ModelPickerPriceCategory, self.model_picker_price_category) result["ModelPolicy"] = to_class(ModelPolicy, self.model_policy) result["ModelPolicyState"] = to_enum(ModelPolicyState, self.model_policy_state) + result["ModelSetReasoningEffortRequest"] = to_class(ModelSetReasoningEffortRequest, self.model_set_reasoning_effort_request) + result["ModelSetReasoningEffortResult"] = to_class(ModelSetReasoningEffortResult, self.model_set_reasoning_effort_result) result["ModelsListRequest"] = to_class(ModelsListRequest, self.models_list_request) result["ModelSwitchToRequest"] = to_class(ModelSwitchToRequest, self.model_switch_to_request) result["ModelSwitchToResult"] = to_class(ModelSwitchToResult, self.model_switch_to_result) result["ModeSetRequest"] = to_class(ModeSetRequest, self.mode_set_request) result["NameGetResult"] = to_class(NameGetResult, self.name_get_result) + result["NameSetAutoRequest"] = to_class(NameSetAutoRequest, self.name_set_auto_request) + result["NameSetAutoResult"] = to_class(NameSetAutoResult, self.name_set_auto_result) result["NameSetRequest"] = to_class(NameSetRequest, self.name_set_request) + result["OptionsUpdateEnvValueMode"] = to_enum(MCPSetEnvValueModeDetails, self.options_update_env_value_mode) + result["PendingPermissionRequest"] = to_class(PendingPermissionRequest, self.pending_permission_request) + result["PendingPermissionRequestList"] = to_class(PendingPermissionRequestList, self.pending_permission_request_list) result["PermissionDecision"] = to_class(PermissionDecision, self.permission_decision) + result["PermissionDecisionApproved"] = to_class(PermissionDecisionApproved, self.permission_decision_approved) + result["PermissionDecisionApprovedForLocation"] = to_class(PermissionDecisionApprovedForLocation, self.permission_decision_approved_for_location) + result["PermissionDecisionApprovedForSession"] = to_class(PermissionDecisionApprovedForSession, self.permission_decision_approved_for_session) result["PermissionDecisionApproveForLocation"] = to_class(PermissionDecisionApproveForLocation, self.permission_decision_approve_for_location) result["PermissionDecisionApproveForLocationApproval"] = to_class(PermissionDecisionApproveForLocationApproval, self.permission_decision_approve_for_location_approval) result["PermissionDecisionApproveForLocationApprovalCommands"] = to_class(PermissionDecisionApproveForLocationApprovalCommands, self.permission_decision_approve_for_location_approval_commands) @@ -8149,14 +15206,50 @@ def to_dict(self) -> dict: result["PermissionDecisionApproveForSessionApprovalWrite"] = to_class(PermissionDecisionApproveForSessionApprovalWrite, self.permission_decision_approve_for_session_approval_write) result["PermissionDecisionApproveOnce"] = to_class(PermissionDecisionApproveOnce, self.permission_decision_approve_once) result["PermissionDecisionApprovePermanently"] = to_class(PermissionDecisionApprovePermanently, self.permission_decision_approve_permanently) + result["PermissionDecisionCancelled"] = to_class(PermissionDecisionCancelled, self.permission_decision_cancelled) + result["PermissionDecisionDeniedByContentExclusionPolicy"] = to_class(PermissionDecisionDeniedByContentExclusionPolicy, self.permission_decision_denied_by_content_exclusion_policy) + result["PermissionDecisionDeniedByPermissionRequestHook"] = to_class(PermissionDecisionDeniedByPermissionRequestHook, self.permission_decision_denied_by_permission_request_hook) + result["PermissionDecisionDeniedByRules"] = to_class(PermissionDecisionDeniedByRules, self.permission_decision_denied_by_rules) + result["PermissionDecisionDeniedInteractivelyByUser"] = to_class(PermissionDecisionDeniedInteractivelyByUser, self.permission_decision_denied_interactively_by_user) + result["PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser"] = to_class(PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser, self.permission_decision_denied_no_approval_rule_and_could_not_request_from_user) result["PermissionDecisionReject"] = to_class(PermissionDecisionReject, self.permission_decision_reject) result["PermissionDecisionRequest"] = to_class(PermissionDecisionRequest, self.permission_decision_request) result["PermissionDecisionUserNotAvailable"] = to_class(PermissionDecisionUserNotAvailable, self.permission_decision_user_not_available) + result["PermissionPathsAddParams"] = to_class(PermissionPathsAddParams, self.permission_paths_add_params) + result["PermissionPathsAllowedCheckParams"] = to_class(PermissionPathsAllowedCheckParams, self.permission_paths_allowed_check_params) + result["PermissionPathsAllowedCheckResult"] = to_class(PermissionPathsAllowedCheckResult, self.permission_paths_allowed_check_result) + result["PermissionPathsConfig"] = to_class(PermissionPathsConfig, self.permission_paths_config) + result["PermissionPathsList"] = to_class(PermissionPathsList, self.permission_paths_list) + result["PermissionPathsUpdatePrimaryParams"] = to_class(PermissionPathsUpdatePrimaryParams, self.permission_paths_update_primary_params) + result["PermissionPathsWorkspaceCheckParams"] = to_class(PermissionPathsWorkspaceCheckParams, self.permission_paths_workspace_check_params) + result["PermissionPathsWorkspaceCheckResult"] = to_class(PermissionPathsWorkspaceCheckResult, self.permission_paths_workspace_check_result) + result["PermissionPromptShownNotification"] = to_class(PermissionPromptShownNotification, self.permission_prompt_shown_notification) result["PermissionRequestResult"] = to_class(PermissionRequestResult, self.permission_request_result) + result["PermissionRulesSet"] = to_class(PermissionRulesSet, self.permission_rules_set) + result["PermissionsConfigureAdditionalContentExclusionPolicy"] = to_class(PermissionsConfigureAdditionalContentExclusionPolicy, self.permissions_configure_additional_content_exclusion_policy) + result["PermissionsConfigureAdditionalContentExclusionPolicyRule"] = to_class(PermissionsConfigureAdditionalContentExclusionPolicyRule, self.permissions_configure_additional_content_exclusion_policy_rule) + result["PermissionsConfigureAdditionalContentExclusionPolicyRuleSource"] = to_class(PermissionsConfigureAdditionalContentExclusionPolicyRuleSource, self.permissions_configure_additional_content_exclusion_policy_rule_source) + result["PermissionsConfigureAdditionalContentExclusionPolicyScope"] = to_enum(PermissionsConfigureAdditionalContentExclusionPolicyScope, self.permissions_configure_additional_content_exclusion_policy_scope) + result["PermissionsConfigureParams"] = to_class(PermissionsConfigureParams, self.permissions_configure_params) + result["PermissionsConfigureResult"] = to_class(PermissionsConfigureResult, self.permissions_configure_result) + result["PermissionsModifyRulesParams"] = to_class(PermissionsModifyRulesParams, self.permissions_modify_rules_params) + result["PermissionsModifyRulesResult"] = to_class(PermissionsModifyRulesResult, self.permissions_modify_rules_result) + result["PermissionsModifyRulesScope"] = to_enum(PermissionsModifyRulesScope, self.permissions_modify_rules_scope) + result["PermissionsNotifyPromptShownResult"] = to_class(PermissionsNotifyPromptShownResult, self.permissions_notify_prompt_shown_result) + result["PermissionsPathsAddResult"] = to_class(PermissionsPathsAddResult, self.permissions_paths_add_result) + result["PermissionsPathsListRequest"] = to_class(PermissionsPathsListRequest, self.permissions_paths_list_request) + result["PermissionsPathsUpdatePrimaryResult"] = to_class(PermissionsPathsUpdatePrimaryResult, self.permissions_paths_update_primary_result) + result["PermissionsPendingRequestsRequest"] = to_class(PermissionsPendingRequestsRequest, self.permissions_pending_requests_request) result["PermissionsResetSessionApprovalsRequest"] = to_class(PermissionsResetSessionApprovalsRequest, self.permissions_reset_session_approvals_request) result["PermissionsResetSessionApprovalsResult"] = to_class(PermissionsResetSessionApprovalsResult, self.permissions_reset_session_approvals_result) result["PermissionsSetApproveAllRequest"] = to_class(PermissionsSetApproveAllRequest, self.permissions_set_approve_all_request) result["PermissionsSetApproveAllResult"] = to_class(PermissionsSetApproveAllResult, self.permissions_set_approve_all_result) + result["PermissionsSetApproveAllSource"] = to_enum(PermissionsSetApproveAllSource, self.permissions_set_approve_all_source) + result["PermissionsSetRequiredRequest"] = to_class(PermissionsSetRequiredRequest, self.permissions_set_required_request) + result["PermissionsSetRequiredResult"] = to_class(PermissionsSetRequiredResult, self.permissions_set_required_result) + result["PermissionsUrlsSetUnrestrictedModeResult"] = to_class(PermissionsUrlsSetUnrestrictedModeResult, self.permissions_urls_set_unrestricted_mode_result) + result["PermissionUrlsConfig"] = to_class(PermissionUrlsConfig, self.permission_urls_config) + result["PermissionUrlsSetUnrestrictedModeParams"] = to_class(PermissionUrlsSetUnrestrictedModeParams, self.permission_urls_set_unrestricted_mode_params) result["PingRequest"] = to_class(PingRequest, self.ping_request) result["PingResult"] = to_class(PingResult, self.ping_result) result["PlanReadResult"] = to_class(PlanReadResult, self.plan_read_result) @@ -8166,13 +15259,45 @@ def to_dict(self) -> dict: result["QueuedCommandHandled"] = to_class(QueuedCommandHandled, self.queued_command_handled) result["QueuedCommandNotHandled"] = to_class(QueuedCommandNotHandled, self.queued_command_not_handled) result["QueuedCommandResult"] = to_class(QueuedCommandResult, self.queued_command_result) + result["QueuePendingItems"] = to_class(QueuePendingItems, self.queue_pending_items) + result["QueuePendingItemsKind"] = to_enum(QueuePendingItemsKind, self.queue_pending_items_kind) + result["QueuePendingItemsResult"] = to_class(QueuePendingItemsResult, self.queue_pending_items_result) + result["QueueRemoveMostRecentResult"] = to_class(QueueRemoveMostRecentResult, self.queue_remove_most_recent_result) + result["RegisterEventInterestParams"] = to_class(RegisterEventInterestParams, self.register_event_interest_params) + result["RegisterEventInterestResult"] = to_class(RegisterEventInterestResult, self.register_event_interest_result) + result["ReleaseEventInterestParams"] = to_class(ReleaseEventInterestParams, self.release_event_interest_params) result["RemoteEnableRequest"] = to_class(RemoteEnableRequest, self.remote_enable_request) result["RemoteEnableResult"] = to_class(RemoteEnableResult, self.remote_enable_result) + result["RemoteNotifySteerableChangedRequest"] = to_class(RemoteNotifySteerableChangedRequest, self.remote_notify_steerable_changed_request) + result["RemoteNotifySteerableChangedResult"] = to_class(RemoteNotifySteerableChangedResult, self.remote_notify_steerable_changed_result) result["RemoteSessionConnectionResult"] = to_class(RemoteSessionConnectionResult, self.remote_session_connection_result) result["RemoteSessionMode"] = to_enum(RemoteSessionMode, self.remote_session_mode) + result["ScheduleEntry"] = to_class(ScheduleEntry, self.schedule_entry) + result["ScheduleList"] = to_class(ScheduleList, self.schedule_list) + result["ScheduleStopRequest"] = to_class(ScheduleStopRequest, self.schedule_stop_request) + result["ScheduleStopResult"] = to_class(ScheduleStopResult, self.schedule_stop_result) + result["SendAgentMode"] = to_enum(SendAgentMode, self.send_agent_mode) + result["SendAttachment"] = to_class(SendAttachment, self.send_attachment) + result["SendAttachmentBlob"] = to_class(SendAttachmentBlob, self.send_attachment_blob) + result["SendAttachmentDirectory"] = to_class(SendAttachmentDirectory, self.send_attachment_directory) + result["SendAttachmentFile"] = to_class(SendAttachmentFile, self.send_attachment_file) + result["SendAttachmentFileLineRange"] = to_class(SendAttachmentFileLineRange, self.send_attachment_file_line_range) + result["SendAttachmentGithubReference"] = to_class(SendAttachmentGithubReference, self.send_attachment_github_reference) + result["SendAttachmentGithubReferenceType"] = to_enum(SendAttachmentGithubReferenceTypeEnum, self.send_attachment_github_reference_type) + result["SendAttachmentSelection"] = to_class(SendAttachmentSelection, self.send_attachment_selection) + result["SendAttachmentSelectionDetails"] = to_class(SendAttachmentSelectionDetails, self.send_attachment_selection_details) + result["SendAttachmentSelectionDetailsEnd"] = to_class(SendAttachmentSelectionDetailsEnd, self.send_attachment_selection_details_end) + result["SendAttachmentSelectionDetailsStart"] = to_class(SendAttachmentSelectionDetailsStart, self.send_attachment_selection_details_start) + result["SendMode"] = to_enum(SendMode, self.send_mode) + result["SendRequest"] = to_class(SendRequest, self.send_request) + result["SendResult"] = to_class(SendResult, self.send_result) result["ServerSkill"] = to_class(ServerSkill, self.server_skill) result["ServerSkillList"] = to_class(ServerSkillList, self.server_skill_list) result["SessionAuthStatus"] = to_class(SessionAuthStatus, self.session_auth_status) + result["SessionBulkDeleteResult"] = to_class(SessionBulkDeleteResult, self.session_bulk_delete_result) + result["SessionContext"] = to_class(SessionContext, self.session_context) + result["SessionContextHostType"] = to_enum(SessionContextHostType, self.session_context_host_type) + result["SessionEnrichMetadataResult"] = to_class(SessionEnrichMetadataResult, self.session_enrich_metadata_result) result["SessionFsAppendFileRequest"] = to_class(SessionFSAppendFileRequest, self.session_fs_append_file_request) result["SessionFsError"] = to_class(SessionFSError, self.session_fs_error) result["SessionFsErrorCode"] = to_enum(SessionFSErrorCode, self.session_fs_error_code) @@ -8201,21 +15326,68 @@ def to_dict(self) -> dict: result["SessionFsStatRequest"] = to_class(SessionFSStatRequest, self.session_fs_stat_request) result["SessionFsStatResult"] = to_class(SessionFSStatResult, self.session_fs_stat_result) result["SessionFsWriteFileRequest"] = to_class(SessionFSWriteFileRequest, self.session_fs_write_file_request) + result["SessionInstalledPlugin"] = to_class(SessionInstalledPlugin, self.session_installed_plugin) + result["SessionInstalledPluginSource"] = from_union([lambda x: to_class(SessionInstalledPluginSource, x), from_str], self.session_installed_plugin_source) + result["SessionInstalledPluginSourceGithub"] = to_class(SessionInstalledPluginSourceGithub, self.session_installed_plugin_source_github) + result["SessionInstalledPluginSourceLocal"] = to_class(SessionInstalledPluginSourceLocal, self.session_installed_plugin_source_local) + result["SessionInstalledPluginSourceUrl"] = to_class(SessionInstalledPluginSourceURL, self.session_installed_plugin_source_url) + result["SessionList"] = to_class(SessionList, self.session_list) + result["SessionLoadDeferredRepoHooksResult"] = to_class(SessionLoadDeferredRepoHooksResult, self.session_load_deferred_repo_hooks_result) result["SessionLogLevel"] = to_enum(SessionLogLevel, self.session_log_level) + result["SessionMetadata"] = to_class(SessionMetadata, self.session_metadata) + result["SessionMetadataSnapshot"] = to_class(SessionMetadataSnapshot, self.session_metadata_snapshot) result["SessionMode"] = to_enum(SessionMode, self.session_mode) + result["SessionPruneResult"] = to_class(SessionPruneResult, self.session_prune_result) + result["SessionsBulkDeleteRequest"] = to_class(SessionsBulkDeleteRequest, self.sessions_bulk_delete_request) + result["SessionsCheckInUseRequest"] = to_class(SessionsCheckInUseRequest, self.sessions_check_in_use_request) + result["SessionsCheckInUseResult"] = to_class(SessionsCheckInUseResult, self.sessions_check_in_use_result) + result["SessionsCloseRequest"] = to_class(SessionsCloseRequest, self.sessions_close_request) + result["SessionsCloseResult"] = to_class(SessionsCloseResult, self.sessions_close_result) + result["SessionsEnrichMetadataRequest"] = to_class(SessionsEnrichMetadataRequest, self.sessions_enrich_metadata_request) + result["SessionSetCredentialsParams"] = to_class(SessionSetCredentialsParams, self.session_set_credentials_params) + result["SessionSetCredentialsResult"] = to_class(SessionSetCredentialsResult, self.session_set_credentials_result) + result["SessionsFindByPrefixRequest"] = to_class(SessionsFindByPrefixRequest, self.sessions_find_by_prefix_request) + result["SessionsFindByPrefixResult"] = to_class(SessionsFindByPrefixResult, self.sessions_find_by_prefix_result) + result["SessionsFindByTaskIDRequest"] = to_class(SessionsFindByTaskIDRequest, self.sessions_find_by_task_id_request) + result["SessionsFindByTaskIDResult"] = to_class(SessionsFindByTaskIDResult, self.sessions_find_by_task_id_result) result["SessionsForkRequest"] = to_class(SessionsForkRequest, self.sessions_fork_request) result["SessionsForkResult"] = to_class(SessionsForkResult, self.sessions_fork_result) + result["SessionsGetEventFilePathRequest"] = to_class(SessionsGetEventFilePathRequest, self.sessions_get_event_file_path_request) + result["SessionsGetEventFilePathResult"] = to_class(SessionsGetEventFilePathResult, self.sessions_get_event_file_path_result) + result["SessionsGetLastForContextRequest"] = to_class(SessionsGetLastForContextRequest, self.sessions_get_last_for_context_request) + result["SessionsGetLastForContextResult"] = to_class(SessionsGetLastForContextResult, self.sessions_get_last_for_context_result) + result["SessionsGetPersistedRemoteSteerableRequest"] = to_class(SessionsGetPersistedRemoteSteerableRequest, self.sessions_get_persisted_remote_steerable_request) + result["SessionsGetPersistedRemoteSteerableResult"] = to_class(SessionsGetPersistedRemoteSteerableResult, self.sessions_get_persisted_remote_steerable_result) + result["SessionSizes"] = to_class(SessionSizes, self.session_sizes) + result["SessionsListRequest"] = to_class(SessionsListRequest, self.sessions_list_request) + result["SessionsLoadDeferredRepoHooksRequest"] = to_class(SessionsLoadDeferredRepoHooksRequest, self.sessions_load_deferred_repo_hooks_request) + result["SessionsPruneOldRequest"] = to_class(SessionsPruneOldRequest, self.sessions_prune_old_request) + result["SessionsReleaseLockRequest"] = to_class(SessionsReleaseLockRequest, self.sessions_release_lock_request) + result["SessionsReleaseLockResult"] = to_class(SessionsReleaseLockResult, self.sessions_release_lock_result) + result["SessionsReloadPluginHooksRequest"] = to_class(SessionsReloadPluginHooksRequest, self.sessions_reload_plugin_hooks_request) + result["SessionsReloadPluginHooksResult"] = to_class(SessionsReloadPluginHooksResult, self.sessions_reload_plugin_hooks_result) + result["SessionsSaveRequest"] = to_class(SessionsSaveRequest, self.sessions_save_request) + result["SessionsSaveResult"] = to_class(SessionsSaveResult, self.sessions_save_result) + result["SessionsSetAdditionalPluginsRequest"] = to_class(SessionsSetAdditionalPluginsRequest, self.sessions_set_additional_plugins_request) + result["SessionsSetAdditionalPluginsResult"] = to_class(SessionsSetAdditionalPluginsResult, self.sessions_set_additional_plugins_result) + result["SessionUpdateOptionsParams"] = to_class(SessionUpdateOptionsParams, self.session_update_options_params) + result["SessionUpdateOptionsResult"] = to_class(SessionUpdateOptionsResult, self.session_update_options_result) + result["SessionWorkingDirectoryContext"] = to_class(SessionWorkingDirectoryContext, self.session_working_directory_context) + result["SessionWorkingDirectoryContextHostType"] = to_enum(SessionContextHostType, self.session_working_directory_context_host_type) result["ShellExecRequest"] = to_class(ShellExecRequest, self.shell_exec_request) result["ShellExecResult"] = to_class(ShellExecResult, self.shell_exec_result) result["ShellKillRequest"] = to_class(ShellKillRequest, self.shell_kill_request) result["ShellKillResult"] = to_class(ShellKillResult, self.shell_kill_result) result["ShellKillSignal"] = to_enum(ShellKillSignal, self.shell_kill_signal) + result["ShutdownRequest"] = to_class(ShutdownRequest, self.shutdown_request) result["Skill"] = to_class(Skill, self.skill) result["SkillList"] = to_class(SkillList, self.skill_list) result["SkillsConfigSetDisabledSkillsRequest"] = to_class(SkillsConfigSetDisabledSkillsRequest, self.skills_config_set_disabled_skills_request) result["SkillsDisableRequest"] = to_class(SkillsDisableRequest, self.skills_disable_request) result["SkillsDiscoverRequest"] = to_class(SkillsDiscoverRequest, self.skills_discover_request) result["SkillsEnableRequest"] = to_class(SkillsEnableRequest, self.skills_enable_request) + result["SkillsGetInvokedResult"] = to_class(SkillsGetInvokedResult, self.skills_get_invoked_result) + result["SkillsInvokedSkill"] = to_class(SkillsInvokedSkill, self.skills_invoked_skill) result["SkillsLoadDiagnostics"] = to_class(SkillsLoadDiagnostics, self.skills_load_diagnostics) result["SlashCommandAgentPromptResult"] = to_class(SlashCommandAgentPromptResult, self.slash_command_agent_prompt_result) result["SlashCommandCompletedResult"] = to_class(SlashCommandCompletedResult, self.slash_command_completed_result) @@ -8226,15 +15398,22 @@ def to_dict(self) -> dict: result["SlashCommandKind"] = to_enum(SlashCommandKind, self.slash_command_kind) result["SlashCommandTextResult"] = to_class(SlashCommandTextResult, self.slash_command_text_result) result["TaskAgentInfo"] = to_class(TaskAgentInfo, self.task_agent_info) + result["TaskAgentProgress"] = to_class(TaskAgentProgress, self.task_agent_progress) result["TaskExecutionMode"] = to_enum(TaskExecutionMode, self.task_execution_mode) result["TaskInfo"] = to_class(TaskInfo, self.task_info) result["TaskList"] = to_class(TaskList, self.task_list) result["TasksCancelRequest"] = to_class(TasksCancelRequest, self.tasks_cancel_request) result["TasksCancelResult"] = to_class(TasksCancelResult, self.tasks_cancel_result) + result["TasksGetCurrentPromotableResult"] = to_class(TasksGetCurrentPromotableResult, self.tasks_get_current_promotable_result) + result["TasksGetProgressRequest"] = to_class(TasksGetProgressRequest, self.tasks_get_progress_request) + result["TasksGetProgressResult"] = to_class(TasksGetProgressResult, self.tasks_get_progress_result) result["TaskShellInfo"] = to_class(TaskShellInfo, self.task_shell_info) result["TaskShellInfoAttachmentMode"] = to_enum(TaskShellInfoAttachmentMode, self.task_shell_info_attachment_mode) + result["TaskShellProgress"] = from_none(self.task_shell_progress) + result["TasksPromoteCurrentToBackgroundResult"] = to_class(TasksPromoteCurrentToBackgroundResult, self.tasks_promote_current_to_background_result) result["TasksPromoteToBackgroundRequest"] = to_class(TasksPromoteToBackgroundRequest, self.tasks_promote_to_background_request) result["TasksPromoteToBackgroundResult"] = to_class(TasksPromoteToBackgroundResult, self.tasks_promote_to_background_result) + result["TasksRefreshResult"] = to_class(TasksRefreshResult, self.tasks_refresh_result) result["TasksRemoveRequest"] = to_class(TasksRemoveRequest, self.tasks_remove_request) result["TasksRemoveResult"] = to_class(TasksRemoveResult, self.tasks_remove_result) result["TasksSendMessageRequest"] = to_class(TasksSendMessageRequest, self.tasks_send_message_request) @@ -8242,9 +15421,14 @@ def to_dict(self) -> dict: result["TasksStartAgentRequest"] = to_class(TasksStartAgentRequest, self.tasks_start_agent_request) result["TasksStartAgentResult"] = to_class(TasksStartAgentResult, self.tasks_start_agent_result) result["TaskStatus"] = to_enum(TaskStatus, self.task_status) + result["TasksWaitForPendingResult"] = to_class(TasksWaitForPendingResult, self.tasks_wait_for_pending_result) + result["TelemetrySetFeatureOverridesRequest"] = to_class(TelemetrySetFeatureOverridesRequest, self.telemetry_set_feature_overrides_request) + result["TokenAuthInfo"] = to_class(TokenAuthInfo, self.token_auth_info) result["Tool"] = to_class(Tool, self.tool) result["ToolList"] = to_class(ToolList, self.tool_list) + result["ToolsInitializeAndValidateResult"] = to_class(ToolsInitializeAndValidateResult, self.tools_initialize_and_validate_result) result["ToolsListRequest"] = to_class(ToolsListRequest, self.tools_list_request) + result["UIAutoModeSwitchResponse"] = to_enum(UIAutoModeSwitchResponse, self.ui_auto_mode_switch_response) result["UIElicitationArrayAnyOfField"] = to_class(UIElicitationArrayAnyOfField, self.ui_elicitation_array_any_of_field) result["UIElicitationArrayAnyOfFieldItems"] = to_class(UIElicitationArrayAnyOfFieldItems, self.ui_elicitation_array_any_of_field_items) result["UIElicitationArrayAnyOfFieldItemsAnyOf"] = to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, self.ui_elicitation_array_any_of_field_items_any_of) @@ -8266,7 +15450,19 @@ def to_dict(self) -> dict: result["UIElicitationStringEnumField"] = to_class(UIElicitationStringEnumField, self.ui_elicitation_string_enum_field) result["UIElicitationStringOneOfField"] = to_class(UIElicitationStringOneOfField, self.ui_elicitation_string_one_of_field) result["UIElicitationStringOneOfFieldOneOf"] = to_class(UIElicitationStringOneOfFieldOneOf, self.ui_elicitation_string_one_of_field_one_of) + result["UIExitPlanModeAction"] = to_enum(UIExitPlanModeAction, self.ui_exit_plan_mode_action) + result["UIExitPlanModeResponse"] = to_class(UIExitPlanModeResponse, self.ui_exit_plan_mode_response) + result["UIHandlePendingAutoModeSwitchRequest"] = to_class(UIHandlePendingAutoModeSwitchRequest, self.ui_handle_pending_auto_mode_switch_request) result["UIHandlePendingElicitationRequest"] = to_class(UIHandlePendingElicitationRequest, self.ui_handle_pending_elicitation_request) + result["UIHandlePendingExitPlanModeRequest"] = to_class(UIHandlePendingExitPlanModeRequest, self.ui_handle_pending_exit_plan_mode_request) + result["UIHandlePendingResult"] = to_class(UIHandlePendingResult, self.ui_handle_pending_result) + result["UIHandlePendingSamplingRequest"] = to_class(UIHandlePendingSamplingRequest, self.ui_handle_pending_sampling_request) + result["UIHandlePendingSamplingResponse"] = from_dict(lambda x: x, self.ui_handle_pending_sampling_response) + result["UIHandlePendingUserInputRequest"] = to_class(UIHandlePendingUserInputRequest, self.ui_handle_pending_user_input_request) + result["UIRegisterDirectAutoModeSwitchHandlerResult"] = to_class(UIRegisterDirectAutoModeSwitchHandlerResult, self.ui_register_direct_auto_mode_switch_handler_result) + result["UIUnregisterDirectAutoModeSwitchHandlerRequest"] = to_class(UIUnregisterDirectAutoModeSwitchHandlerRequest, self.ui_unregister_direct_auto_mode_switch_handler_request) + result["UIUnregisterDirectAutoModeSwitchHandlerResult"] = to_class(UIUnregisterDirectAutoModeSwitchHandlerResult, self.ui_unregister_direct_auto_mode_switch_handler_result) + result["UIUserInputResponse"] = to_class(UIUserInputResponse, self.ui_user_input_response) result["UsageGetMetricsResult"] = to_class(UsageGetMetricsResult, self.usage_get_metrics_result) result["UsageMetricsCodeChanges"] = to_class(UsageMetricsCodeChanges, self.usage_metrics_code_changes) result["UsageMetricsModelMetric"] = to_class(UsageMetricsModelMetric, self.usage_metrics_model_metric) @@ -8274,11 +15470,29 @@ def to_dict(self) -> dict: result["UsageMetricsModelMetricTokenDetail"] = to_class(UsageMetricsModelMetricTokenDetail, self.usage_metrics_model_metric_token_detail) result["UsageMetricsModelMetricUsage"] = to_class(UsageMetricsModelMetricUsage, self.usage_metrics_model_metric_usage) result["UsageMetricsTokenDetail"] = to_class(UsageMetricsTokenDetail, self.usage_metrics_token_detail) + result["UserAuthInfo"] = to_class(UserAuthInfo, self.user_auth_info) + result["UserToolSessionApprovalCommands"] = to_class(UserToolSessionApprovalCommands, self.user_tool_session_approval_commands) + result["UserToolSessionApprovalCustomTool"] = to_class(UserToolSessionApprovalCustomTool, self.user_tool_session_approval_custom_tool) + result["UserToolSessionApprovalExtensionManagement"] = to_class(UserToolSessionApprovalExtensionManagement, self.user_tool_session_approval_extension_management) + result["UserToolSessionApprovalExtensionPermissionAccess"] = to_class(UserToolSessionApprovalExtensionPermissionAccess, self.user_tool_session_approval_extension_permission_access) + result["UserToolSessionApprovalMcp"] = to_class(UserToolSessionApprovalMCP, self.user_tool_session_approval_mcp) + result["UserToolSessionApprovalMemory"] = to_class(UserToolSessionApprovalMemory, self.user_tool_session_approval_memory) + result["UserToolSessionApprovalRead"] = to_class(UserToolSessionApprovalRead, self.user_tool_session_approval_read) + result["UserToolSessionApprovalWrite"] = to_class(UserToolSessionApprovalWrite, self.user_tool_session_approval_write) + result["WorkspacesCheckpoints"] = to_class(WorkspacesCheckpoints, self.workspaces_checkpoints) result["WorkspacesCreateFileRequest"] = to_class(WorkspacesCreateFileRequest, self.workspaces_create_file_request) result["WorkspacesGetWorkspaceResult"] = to_class(WorkspacesGetWorkspaceResult, self.workspaces_get_workspace_result) + result["WorkspacesListCheckpointsResult"] = to_class(WorkspacesListCheckpointsResult, self.workspaces_list_checkpoints_result) result["WorkspacesListFilesResult"] = to_class(WorkspacesListFilesResult, self.workspaces_list_files_result) + result["WorkspacesReadCheckpointRequest"] = to_class(WorkspacesReadCheckpointRequest, self.workspaces_read_checkpoint_request) + result["WorkspacesReadCheckpointResult"] = to_class(WorkspacesReadCheckpointResult, self.workspaces_read_checkpoint_result) result["WorkspacesReadFileRequest"] = to_class(WorkspacesReadFileRequest, self.workspaces_read_file_request) result["WorkspacesReadFileResult"] = to_class(WorkspacesReadFileResult, self.workspaces_read_file_result) + result["WorkspacesSaveLargePasteRequest"] = to_class(WorkspacesSaveLargePasteRequest, self.workspaces_save_large_paste_request) + result["WorkspacesSaveLargePasteResult"] = to_class(WorkspacesSaveLargePasteResult, self.workspaces_save_large_paste_result) + result["SessionContextInfo"] = from_union([lambda x: to_class(SessionContextInfo, x), from_none], self.session_context_info) + result["TaskProgress"] = from_union([lambda x: to_class(TaskProgressClass, x), from_none], self.task_progress) + result["WorkspaceSummary"] = from_union([lambda x: to_class(WorkspaceSummary, x), from_none], self.workspace_summary) return result def rpc_from_dict(s: Any) -> RPC: @@ -8290,8 +15504,14 @@ def rpc_to_dict(x: RPC) -> Any: ExternalToolResult = ExternalToolTextResultForLlm FilterMapping = dict +McpExecuteSamplingRequest = dict +McpExecuteSamplingResult = dict +OptionsUpdateEnvValueMode = MCPSetEnvValueModeDetails +SessionWorkingDirectoryContextHostType = SessionContextHostType TaskInfoExecutionMode = TaskExecutionMode TaskInfoStatus = TaskStatus +TaskProgress = TaskProgressClass +TaskShellProgress = None def _timeout_kwargs(timeout: float | None) -> dict: """Build keyword arguments for optional timeout forwarding.""" @@ -8442,6 +15662,90 @@ async def connect(self, params: ConnectRemoteSessionParams, *, timeout: float | params_dict = {k: v for k, v in params.to_dict().items() if v is not None} return RemoteSessionConnectionResult.from_dict(await self._client.request("sessions.connect", params_dict, **_timeout_kwargs(timeout))) + async def list(self, params: SessionsListRequest, *, timeout: float | None = None) -> SessionList: + "Lists persisted sessions, optionally filtered by working-directory context.\n\nArgs:\n params: Optional metadata-load limit and context filter applied to the returned sessions.\n\nReturns:\n Persisted sessions matching the filter, ordered most-recently-modified first." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionList.from_dict(await self._client.request("sessions.list", params_dict, **_timeout_kwargs(timeout))) + + async def find_by_task_id(self, params: SessionsFindByTaskIDRequest, *, timeout: float | None = None) -> SessionsFindByTaskIDResult: + "Finds the local session bound to a GitHub task ID, if any.\n\nArgs:\n params: GitHub task ID to look up.\n\nReturns:\n ID of the local session bound to the given GitHub task, or omitted when none." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsFindByTaskIDResult.from_dict(await self._client.request("sessions.findByTaskId", params_dict, **_timeout_kwargs(timeout))) + + async def find_by_prefix(self, params: SessionsFindByPrefixRequest, *, timeout: float | None = None) -> SessionsFindByPrefixResult: + "Resolves a UUID prefix to a unique session ID, if exactly one session matches.\n\nArgs:\n params: UUID prefix to resolve to a unique session ID.\n\nReturns:\n Session ID matching the prefix, omitted when no unique match exists." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsFindByPrefixResult.from_dict(await self._client.request("sessions.findByPrefix", params_dict, **_timeout_kwargs(timeout))) + + async def get_last_for_context(self, params: SessionsGetLastForContextRequest, *, timeout: float | None = None) -> SessionsGetLastForContextResult: + "Returns the most-relevant prior session for a given working-directory context.\n\nArgs:\n params: Optional working-directory context used to score session relevance.\n\nReturns:\n Most-relevant session ID for the supplied context, or omitted when no sessions exist." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsGetLastForContextResult.from_dict(await self._client.request("sessions.getLastForContext", params_dict, **_timeout_kwargs(timeout))) + + async def get_event_file_path(self, params: SessionsGetEventFilePathRequest, *, timeout: float | None = None) -> SessionsGetEventFilePathResult: + "Computes the absolute path to a session's persisted events.jsonl file.\n\nArgs:\n params: Session ID whose event-log file path to compute.\n\nReturns:\n Absolute path to the session's events.jsonl file on disk." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsGetEventFilePathResult.from_dict(await self._client.request("sessions.getEventFilePath", params_dict, **_timeout_kwargs(timeout))) + + async def get_sizes(self, *, timeout: float | None = None) -> SessionSizes: + "Returns the on-disk byte size of each session's workspace directory.\n\nReturns:\n Map of sessionId -> on-disk size in bytes for each session's workspace directory." + return SessionSizes.from_dict(await self._client.request("sessions.getSizes", {}, **_timeout_kwargs(timeout))) + + async def check_in_use(self, params: SessionsCheckInUseRequest, *, timeout: float | None = None) -> SessionsCheckInUseResult: + "Returns the subset of the supplied session IDs that are currently held by another running process.\n\nArgs:\n params: Session IDs to test for live in-use locks.\n\nReturns:\n Session IDs from the input set that are currently in use by another process." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsCheckInUseResult.from_dict(await self._client.request("sessions.checkInUse", params_dict, **_timeout_kwargs(timeout))) + + async def get_persisted_remote_steerable(self, params: SessionsGetPersistedRemoteSteerableRequest, *, timeout: float | None = None) -> SessionsGetPersistedRemoteSteerableResult: + "Returns a session's persisted remote-steerable flag, if any has been recorded.\n\nArgs:\n params: Session ID to look up the persisted remote-steerable flag for.\n\nReturns:\n The session's persisted remote-steerable flag, or omitted when no value has been persisted." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsGetPersistedRemoteSteerableResult.from_dict(await self._client.request("sessions.getPersistedRemoteSteerable", params_dict, **_timeout_kwargs(timeout))) + + async def close(self, params: SessionsCloseRequest, *, timeout: float | None = None) -> SessionsCloseResult: + "Closes a session: emits shutdown, flushes pending events, releases the in-use lock, and disposes the active session.\n\nArgs:\n params: Session ID to close.\n\nReturns:\n Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsCloseResult.from_dict(await self._client.request("sessions.close", params_dict, **_timeout_kwargs(timeout))) + + async def bulk_delete(self, params: SessionsBulkDeleteRequest, *, timeout: float | None = None) -> SessionBulkDeleteResult: + "Closes, deactivates, and deletes a set of sessions, returning the bytes freed per session.\n\nArgs:\n params: Session IDs to close, deactivate, and delete from disk.\n\nReturns:\n Map of sessionId -> bytes freed by removing the session's workspace directory." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionBulkDeleteResult.from_dict(await self._client.request("sessions.bulkDelete", params_dict, **_timeout_kwargs(timeout))) + + async def prune_old(self, params: SessionsPruneOldRequest, *, timeout: float | None = None) -> SessionPruneResult: + "Deletes sessions older than the given threshold, with optional dry-run and exclusion list.\n\nArgs:\n params: Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true).\n\nReturns:\n Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionPruneResult.from_dict(await self._client.request("sessions.pruneOld", params_dict, **_timeout_kwargs(timeout))) + + async def save(self, params: SessionsSaveRequest, *, timeout: float | None = None) -> SessionsSaveResult: + "Flushes a session's pending events to disk.\n\nArgs:\n params: Session ID whose pending events should be flushed to disk.\n\nReturns:\n Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed)." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsSaveResult.from_dict(await self._client.request("sessions.save", params_dict, **_timeout_kwargs(timeout))) + + async def release_lock(self, params: SessionsReleaseLockRequest, *, timeout: float | None = None) -> SessionsReleaseLockResult: + "Releases the in-use lock held by this process for a session.\n\nArgs:\n params: Session ID whose in-use lock should be released.\n\nReturns:\n Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsReleaseLockResult.from_dict(await self._client.request("sessions.releaseLock", params_dict, **_timeout_kwargs(timeout))) + + async def enrich_metadata(self, params: SessionsEnrichMetadataRequest, *, timeout: float | None = None) -> SessionEnrichMetadataResult: + "Backfills missing summary and context fields on the supplied session metadata records.\n\nArgs:\n params: Session metadata records to enrich with summary and context information.\n\nReturns:\n The same metadata records, with summary and context fields backfilled where available." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionEnrichMetadataResult.from_dict(await self._client.request("sessions.enrichMetadata", params_dict, **_timeout_kwargs(timeout))) + + async def reload_plugin_hooks(self, params: SessionsReloadPluginHooksRequest, *, timeout: float | None = None) -> SessionsReloadPluginHooksResult: + "Reloads user, plugin, and (optionally) repo hooks on the active session.\n\nArgs:\n params: Active session ID and an optional flag for deferring repo-level hooks until folder trust.\n\nReturns:\n Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsReloadPluginHooksResult.from_dict(await self._client.request("sessions.reloadPluginHooks", params_dict, **_timeout_kwargs(timeout))) + + async def load_deferred_repo_hooks(self, params: SessionsLoadDeferredRepoHooksRequest, *, timeout: float | None = None) -> SessionLoadDeferredRepoHooksResult: + "Loads previously-deferred repo-level hooks on the active session, returning queued startup prompts.\n\nArgs:\n params: Active session ID whose deferred repo-level hooks should be loaded.\n\nReturns:\n Queued repo-level startup prompts and the total hook command count after loading." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionLoadDeferredRepoHooksResult.from_dict(await self._client.request("sessions.loadDeferredRepoHooks", params_dict, **_timeout_kwargs(timeout))) + + async def set_additional_plugins(self, params: SessionsSetAdditionalPluginsRequest, *, timeout: float | None = None) -> SessionsSetAdditionalPluginsResult: + "Replaces the manager-wide additional plugins registered with the session manager.\n\nArgs:\n params: Manager-wide additional plugins to register; replaces any previously-configured set.\n\nReturns:\n Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload." + params_dict = {k: v for k, v in params.to_dict().items() if v is not None} + return SessionsSetAdditionalPluginsResult.from_dict(await self._client.request("sessions.setAdditionalPlugins", params_dict, **_timeout_kwargs(timeout))) + class ServerRpc: """Typed server-scoped RPC methods.""" @@ -8456,7 +15760,7 @@ def __init__(self, client: "JsonRpcClient"): self.sessions = ServerSessionsApi(client) async def ping(self, params: PingRequest, *, timeout: float | None = None) -> PingResult: - "Checks server responsiveness and returns protocol information.\n\nArgs:\n params: Optional message to echo back to the caller.\n\nReturns:\n Server liveness response, including the echoed message, current timestamp, and protocol version." + "Checks server responsiveness and returns protocol information.\n\nArgs:\n params: Optional message to echo back to the caller.\n\nReturns:\n Server liveness response, including the echoed message, current server timestamp, and protocol version." 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))) @@ -8481,6 +15785,12 @@ async def get_status(self, *, timeout: float | None = None) -> SessionAuthStatus "Gets authentication status and account metadata for the session.\n\nReturns:\n Authentication status and account metadata for the session." return SessionAuthStatus.from_dict(await self._client.request("session.auth.getStatus", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def set_credentials(self, params: SessionSetCredentialsParams, *, timeout: float | None = None) -> SessionSetCredentialsResult: + "Updates the session's auth credentials used for outbound model and API requests.\n\nArgs:\n params: New auth credentials to install on the session. Omit to leave credentials unchanged.\n\nReturns:\n Indicates whether the credential update succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return SessionSetCredentialsResult.from_dict(await self._client.request("session.auth.setCredentials", params_dict, **_timeout_kwargs(timeout))) + class ModelApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8488,7 +15798,7 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._session_id = session_id async def get_current(self, *, timeout: float | None = None) -> CurrentModel: - "Gets the currently selected model for the session.\n\nReturns:\n The currently selected model for the session." + "Gets the currently selected model for the session.\n\nReturns:\n The currently selected model and reasoning effort for the session." return CurrentModel.from_dict(await self._client.request("session.model.getCurrent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def switch_to(self, params: ModelSwitchToRequest, *, timeout: float | None = None) -> ModelSwitchToResult: @@ -8497,6 +15807,12 @@ async def switch_to(self, params: ModelSwitchToRequest, *, timeout: float | None params_dict["sessionId"] = self._session_id return ModelSwitchToResult.from_dict(await self._client.request("session.model.switchTo", params_dict, **_timeout_kwargs(timeout))) + async def set_reasoning_effort(self, params: ModelSetReasoningEffortRequest, *, timeout: float | None = None) -> ModelSetReasoningEffortResult: + "Updates the session's reasoning effort without changing the selected model.\n\nArgs:\n params: Reasoning effort level to apply to the currently selected model.\n\nReturns:\n Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return ModelSetReasoningEffortResult.from_dict(await self._client.request("session.model.setReasoningEffort", params_dict, **_timeout_kwargs(timeout))) + class ModeApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8529,6 +15845,12 @@ async def set(self, params: NameSetRequest, *, timeout: float | None = None) -> params_dict["sessionId"] = self._session_id await self._client.request("session.name.set", params_dict, **_timeout_kwargs(timeout)) + async def set_auto(self, params: NameSetAutoRequest, *, timeout: float | None = None) -> NameSetAutoResult: + "Persists an auto-generated session summary as the session's name when no user-set name exists.\n\nArgs:\n params: Auto-generated session summary to apply as the session's name when no user-set name exists.\n\nReturns:\n Indicates whether the auto-generated summary was applied as the session's name." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return NameSetAutoResult.from_dict(await self._client.request("session.name.setAuto", params_dict, **_timeout_kwargs(timeout))) + class PlanApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8556,7 +15878,7 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._session_id = session_id async def get_workspace(self, *, timeout: float | None = None) -> WorkspacesGetWorkspaceResult: - "Gets current workspace metadata for the session.\n\nReturns:\n Current workspace metadata for the session, or null when not available." + "Gets current workspace metadata for the session.\n\nReturns:\n Current workspace metadata for the session, including its absolute filesystem path when available." return WorkspacesGetWorkspaceResult.from_dict(await self._client.request("session.workspaces.getWorkspace", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def list_files(self, *, timeout: float | None = None) -> WorkspacesListFilesResult: @@ -8575,6 +15897,22 @@ async def create_file(self, params: WorkspacesCreateFileRequest, *, timeout: flo params_dict["sessionId"] = self._session_id await self._client.request("session.workspaces.createFile", params_dict, **_timeout_kwargs(timeout)) + async def list_checkpoints(self, *, timeout: float | None = None) -> WorkspacesListCheckpointsResult: + "Lists workspace checkpoints in chronological order.\n\nReturns:\n Workspace checkpoints in chronological order; empty when the workspace is not enabled." + return WorkspacesListCheckpointsResult.from_dict(await self._client.request("session.workspaces.listCheckpoints", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def read_checkpoint(self, params: WorkspacesReadCheckpointRequest, *, timeout: float | None = None) -> WorkspacesReadCheckpointResult: + "Reads the content of a workspace checkpoint by number.\n\nArgs:\n params: Checkpoint number to read.\n\nReturns:\n Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return WorkspacesReadCheckpointResult.from_dict(await self._client.request("session.workspaces.readCheckpoint", params_dict, **_timeout_kwargs(timeout))) + + async def save_large_paste(self, params: WorkspacesSaveLargePasteRequest, *, timeout: float | None = None) -> WorkspacesSaveLargePasteResult: + "Saves pasted content as a UTF-8 file in the session workspace.\n\nArgs:\n params: Pasted content to save as a UTF-8 file in the session workspace.\n\nReturns:\n Descriptor for the saved paste file, or null when the workspace is unavailable." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return WorkspacesSaveLargePasteResult.from_dict(await self._client.request("session.workspaces.saveLargePaste", params_dict, **_timeout_kwargs(timeout))) + class InstructionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8644,12 +15982,34 @@ async def list(self, *, timeout: float | None = None) -> TaskList: "Lists background tasks tracked by the session.\n\nReturns:\n Background tasks currently tracked by the session." return TaskList.from_dict(await self._client.request("session.tasks.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def refresh(self, *, timeout: float | None = None) -> TasksRefreshResult: + "Refreshes metadata for any detached background shells the runtime knows about.\n\nReturns:\n Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop." + return TasksRefreshResult.from_dict(await self._client.request("session.tasks.refresh", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def wait_for_pending(self, *, timeout: float | None = None) -> TasksWaitForPendingResult: + "Waits for all in-flight background tasks and any follow-up turns to settle.\n\nReturns:\n Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS)." + return TasksWaitForPendingResult.from_dict(await self._client.request("session.tasks.waitForPending", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def get_progress(self, params: TasksGetProgressRequest, *, timeout: float | None = None) -> TasksGetProgressResult: + "Returns progress information for a background task by ID.\n\nArgs:\n params: Identifier of the background task to fetch progress for.\n\nReturns:\n Progress information for the task, or null when no task with that ID is tracked." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return TasksGetProgressResult.from_dict(await self._client.request("session.tasks.getProgress", params_dict, **_timeout_kwargs(timeout))) + + async def get_current_promotable(self, *, timeout: float | None = None) -> TasksGetCurrentPromotableResult: + "Returns the first sync-waiting task that can currently be promoted to background mode.\n\nReturns:\n The first sync-waiting task that can currently be promoted to background mode." + return TasksGetCurrentPromotableResult.from_dict(await self._client.request("session.tasks.getCurrentPromotable", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def promote_to_background(self, params: TasksPromoteToBackgroundRequest, *, timeout: float | None = None) -> TasksPromoteToBackgroundResult: "Promotes an eligible synchronously-waited task so it continues running in the background.\n\nArgs:\n params: Identifier of the task to promote to background mode.\n\nReturns:\n Indicates whether the task was successfully promoted to background mode." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return TasksPromoteToBackgroundResult.from_dict(await self._client.request("session.tasks.promoteToBackground", params_dict, **_timeout_kwargs(timeout))) + async def promote_current_to_background(self, *, timeout: float | None = None) -> TasksPromoteCurrentToBackgroundResult: + "Atomically promotes the first promotable sync-waiting task to background mode and returns it.\n\nReturns:\n The promoted task as it now exists in background mode, omitted if no promotable task was waiting." + return TasksPromoteCurrentToBackgroundResult.from_dict(await self._client.request("session.tasks.promoteCurrentToBackground", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def cancel(self, params: TasksCancelRequest, *, timeout: float | None = None) -> TasksCancelResult: "Cancels a background task.\n\nArgs:\n params: Identifier of the background task to cancel.\n\nReturns:\n Indicates whether the background task was successfully cancelled." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} @@ -8679,6 +16039,10 @@ async def list(self, *, timeout: float | None = None) -> SkillList: "Lists skills available to the session.\n\nReturns:\n Skills available to the session, with their enabled state." return SkillList.from_dict(await self._client.request("session.skills.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def get_invoked(self, *, timeout: float | None = None) -> SkillsGetInvokedResult: + "Returns the skills that have been invoked during this session.\n\nReturns:\n Skills invoked during this session, ordered by invocation time (most recent last)." + return SkillsGetInvokedResult.from_dict(await self._client.request("session.skills.getInvoked", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def enable(self, params: SkillsEnableRequest, *, timeout: float | None = None) -> None: "Enables a skill for the session.\n\nArgs:\n params: Name of the skill to enable for the session." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} @@ -8695,6 +16059,10 @@ async def reload(self, *, timeout: float | None = None) -> SkillsLoadDiagnostics "Reloads skill definitions for the session.\n\nReturns:\n Diagnostics from reloading skill definitions, with warnings and errors as separate lists." return SkillsLoadDiagnostics.from_dict(await self._client.request("session.skills.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def ensure_loaded(self, *, timeout: float | None = None) -> None: + "Ensures the session's skill definitions have been loaded from disk." + await self._client.request("session.skills.ensureLoaded", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) + # Experimental: this API group is experimental and may change or be removed. class McpOauthApi: @@ -8736,6 +16104,28 @@ async def reload(self, *, timeout: float | None = None) -> None: "Reloads MCP server connections for the session." await self._client.request("session.mcp.reload", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) + async def execute_sampling(self, params: MCPExecuteSamplingParams, *, timeout: float | None = None) -> MCPSamplingExecutionResult: + "Runs an MCP sampling inference on behalf of an MCP server.\n\nArgs:\n params: Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference.\n\nReturns:\n Outcome of an MCP sampling execution: success result, failure error, or cancellation." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MCPSamplingExecutionResult.from_dict(await self._client.request("session.mcp.executeSampling", params_dict, **_timeout_kwargs(timeout))) + + async def cancel_sampling_execution(self, params: MCPCancelSamplingExecutionParams, *, timeout: float | None = None) -> MCPCancelSamplingExecutionResult: + "Cancels an in-flight MCP sampling execution by request ID.\n\nArgs:\n params: The requestId previously passed to executeSampling that should be cancelled.\n\nReturns:\n Indicates whether an in-flight sampling execution with the given requestId was found and cancelled." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MCPCancelSamplingExecutionResult.from_dict(await self._client.request("session.mcp.cancelSamplingExecution", params_dict, **_timeout_kwargs(timeout))) + + async def set_env_value_mode(self, params: MCPSetEnvValueModeParams, *, timeout: float | None = None) -> MCPSetEnvValueModeResult: + "Sets how environment-variable values supplied to MCP servers are resolved (direct or indirect).\n\nArgs:\n params: Mode controlling how MCP server env values are resolved (`direct` or `indirect`).\n\nReturns:\n Env-value mode recorded on the session after the update." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MCPSetEnvValueModeResult.from_dict(await self._client.request("session.mcp.setEnvValueMode", params_dict, **_timeout_kwargs(timeout))) + + async def remove_git_hub(self, *, timeout: float | None = None) -> MCPRemoveGitHubResult: + "Removes the auto-managed `github` MCP server when present.\n\nReturns:\n Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove)." + return MCPRemoveGitHubResult.from_dict(await self._client.request("session.mcp.removeGitHub", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + # Experimental: this API group is experimental and may change or be removed. class PluginsApi: @@ -8748,6 +16138,32 @@ async def list(self, *, timeout: float | None = None) -> PluginList: return PluginList.from_dict(await self._client.request("session.plugins.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. +class OptionsApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def update(self, params: SessionUpdateOptionsParams, *, timeout: float | None = None) -> SessionUpdateOptionsResult: + "Patches the genuinely-mutable subset of session options.\n\nArgs:\n params: Patch of mutable session options to apply to the running session.\n\nReturns:\n Indicates whether the session options patch was applied successfully." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return SessionUpdateOptionsResult.from_dict(await self._client.request("session.options.update", params_dict, **_timeout_kwargs(timeout))) + + +# Experimental: this API group is experimental and may change or be removed. +class LspApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def initialize(self, params: LspInitializeRequest, *, timeout: float | None = None) -> None: + "Loads the merged LSP configuration set for the session's working directory.\n\nArgs:\n params: Parameters for (re)loading the merged LSP configuration set." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + await self._client.request("session.lsp.initialize", params_dict, **_timeout_kwargs(timeout)) + + # Experimental: this API group is experimental and may change or be removed. class ExtensionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8786,6 +16202,10 @@ async def handle_pending_tool_call(self, params: HandlePendingToolCallRequest, * params_dict["sessionId"] = self._session_id return HandlePendingToolCallResult.from_dict(await self._client.request("session.tools.handlePendingToolCall", params_dict, **_timeout_kwargs(timeout))) + async def initialize_and_validate(self, *, timeout: float | None = None) -> ToolsInitializeAndValidateResult: + "Resolves, builds, and validates the runtime tool list for the session.\n\nReturns:\n Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation." + return ToolsInitializeAndValidateResult.from_dict(await self._client.request("session.tools.initializeAndValidate", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + class CommandsApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8810,13 +16230,38 @@ async def handle_pending_command(self, params: CommandsHandlePendingCommandReque params_dict["sessionId"] = self._session_id return CommandsHandlePendingCommandResult.from_dict(await self._client.request("session.commands.handlePendingCommand", params_dict, **_timeout_kwargs(timeout))) + async def execute(self, params: ExecuteCommandParams, *, timeout: float | None = None) -> ExecuteCommandResult: + "Executes a slash command synchronously and returns any error.\n\nArgs:\n params: Slash command name and argument string to execute synchronously.\n\nReturns:\n Error message produced while executing the command, if any." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return ExecuteCommandResult.from_dict(await self._client.request("session.commands.execute", params_dict, **_timeout_kwargs(timeout))) + + async def enqueue(self, params: EnqueueCommandParams, *, timeout: float | None = None) -> EnqueueCommandResult: + "Enqueues a slash command for FIFO processing on the local session.\n\nArgs:\n params: Slash-prefixed command string to enqueue for FIFO processing.\n\nReturns:\n Indicates whether the command was accepted into the local execution queue." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return EnqueueCommandResult.from_dict(await self._client.request("session.commands.enqueue", params_dict, **_timeout_kwargs(timeout))) + async def respond_to_queued_command(self, params: CommandsRespondToQueuedCommandRequest, *, timeout: float | None = None) -> CommandsRespondToQueuedCommandResult: - "Responds to a queued command request from the session.\n\nArgs:\n params: Queued command request ID and the result indicating whether the client handled it.\n\nReturns:\n Indicates whether the queued-command response was accepted by the session." + "Reports whether the host actually executed a queued command and whether to continue processing.\n\nArgs:\n params: Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands).\n\nReturns:\n Indicates whether the queued-command response was matched to a pending request." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return CommandsRespondToQueuedCommandResult.from_dict(await self._client.request("session.commands.respondToQueuedCommand", params_dict, **_timeout_kwargs(timeout))) +# Experimental: this API group is experimental and may change or be removed. +class TelemetryApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def set_feature_overrides(self, params: TelemetrySetFeatureOverridesRequest, *, timeout: float | None = None) -> None: + "Sets feature override key/value pairs to attach to subsequent telemetry events for the session.\n\nArgs:\n params: Feature override key/value pairs to attach to subsequent telemetry events from this session." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + await self._client.request("session.telemetry.setFeatureOverrides", params_dict, **_timeout_kwargs(timeout)) + + class UiApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client @@ -8834,11 +16279,99 @@ async def handle_pending_elicitation(self, params: UIHandlePendingElicitationReq params_dict["sessionId"] = self._session_id return UIElicitationResult.from_dict(await self._client.request("session.ui.handlePendingElicitation", params_dict, **_timeout_kwargs(timeout))) + async def handle_pending_user_input(self, params: UIHandlePendingUserInputRequest, *, timeout: float | None = None) -> UIHandlePendingResult: + "Resolves a pending `user_input.requested` event with the user's response.\n\nArgs:\n params: Request ID of a pending `user_input.requested` event and the user's response.\n\nReturns:\n Indicates whether the pending UI request was resolved by this call." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return UIHandlePendingResult.from_dict(await self._client.request("session.ui.handlePendingUserInput", params_dict, **_timeout_kwargs(timeout))) + + async def handle_pending_sampling(self, params: UIHandlePendingSamplingRequest, *, timeout: float | None = None) -> UIHandlePendingResult: + "Resolves a pending `sampling.requested` event with a sampling result, or rejects it.\n\nArgs:\n params: Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject).\n\nReturns:\n Indicates whether the pending UI request was resolved by this call." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return UIHandlePendingResult.from_dict(await self._client.request("session.ui.handlePendingSampling", params_dict, **_timeout_kwargs(timeout))) + + async def handle_pending_auto_mode_switch(self, params: UIHandlePendingAutoModeSwitchRequest, *, timeout: float | None = None) -> UIHandlePendingResult: + "Resolves a pending `auto_mode_switch.requested` event with the user's accept/decline decision.\n\nArgs:\n params: Request ID of a pending `auto_mode_switch.requested` event and the user's response.\n\nReturns:\n Indicates whether the pending UI request was resolved by this call." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return UIHandlePendingResult.from_dict(await self._client.request("session.ui.handlePendingAutoModeSwitch", params_dict, **_timeout_kwargs(timeout))) + + async def handle_pending_exit_plan_mode(self, params: UIHandlePendingExitPlanModeRequest, *, timeout: float | None = None) -> UIHandlePendingResult: + "Resolves a pending `exit_plan_mode.requested` event with the user's response.\n\nArgs:\n params: Request ID of a pending `exit_plan_mode.requested` event and the user's response.\n\nReturns:\n Indicates whether the pending UI request was resolved by this call." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return UIHandlePendingResult.from_dict(await self._client.request("session.ui.handlePendingExitPlanMode", params_dict, **_timeout_kwargs(timeout))) + + async def register_direct_auto_mode_switch_handler(self, *, timeout: float | None = None) -> UIRegisterDirectAutoModeSwitchHandlerResult: + "Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch.\n\nReturns:\n Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId)." + return UIRegisterDirectAutoModeSwitchHandlerResult.from_dict(await self._client.request("session.ui.registerDirectAutoModeSwitchHandler", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def unregister_direct_auto_mode_switch_handler(self, params: UIUnregisterDirectAutoModeSwitchHandlerRequest, *, timeout: float | None = None) -> UIUnregisterDirectAutoModeSwitchHandlerResult: + "Unregisters a previously-registered in-process auto-mode-switch handler by its opaque handle.\n\nArgs:\n params: Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release.\n\nReturns:\n Indicates whether the handle was active and the registration count was decremented." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return UIUnregisterDirectAutoModeSwitchHandlerResult.from_dict(await self._client.request("session.ui.unregisterDirectAutoModeSwitchHandler", params_dict, **_timeout_kwargs(timeout))) + + +class PermissionsPathsApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def list(self, *, timeout: float | None = None) -> PermissionPathsList: + "Returns the session's allowed directories and primary working directory.\n\nReturns:\n Snapshot of the session's allow-listed directories and primary working directory." + return PermissionPathsList.from_dict(await self._client.request("session.permissions.paths.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def add(self, params: PermissionPathsAddParams, *, timeout: float | None = None) -> PermissionsPathsAddResult: + "Adds a directory to the session's allow-list.\n\nArgs:\n params: Directory path to add to the session's allowed directories.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsPathsAddResult.from_dict(await self._client.request("session.permissions.paths.add", params_dict, **_timeout_kwargs(timeout))) + + async def update_primary(self, params: PermissionPathsUpdatePrimaryParams, *, timeout: float | None = None) -> PermissionsPathsUpdatePrimaryResult: + "Updates the session's primary working directory used by the permission policy.\n\nArgs:\n params: Directory path to set as the session's new primary working directory.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsPathsUpdatePrimaryResult.from_dict(await self._client.request("session.permissions.paths.updatePrimary", params_dict, **_timeout_kwargs(timeout))) + + async def is_path_within_allowed_directories(self, params: PermissionPathsAllowedCheckParams, *, timeout: float | None = None) -> PermissionPathsAllowedCheckResult: + "Reports whether a path falls within any of the session's allowed directories.\n\nArgs:\n params: Path to evaluate against the session's allowed directories.\n\nReturns:\n Indicates whether the supplied path is within the session's allowed directories." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionPathsAllowedCheckResult.from_dict(await self._client.request("session.permissions.paths.isPathWithinAllowedDirectories", params_dict, **_timeout_kwargs(timeout))) + + async def is_path_within_workspace(self, params: PermissionPathsWorkspaceCheckParams, *, timeout: float | None = None) -> PermissionPathsWorkspaceCheckResult: + "Reports whether a path falls within the session's workspace (primary) directory.\n\nArgs:\n params: Path to evaluate against the session's workspace (primary) directory.\n\nReturns:\n Indicates whether the supplied path is within the session's workspace directory." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionPathsWorkspaceCheckResult.from_dict(await self._client.request("session.permissions.paths.isPathWithinWorkspace", params_dict, **_timeout_kwargs(timeout))) + + +class PermissionsUrlsApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def set_unrestricted_mode(self, params: PermissionUrlsSetUnrestrictedModeParams, *, timeout: float | None = None) -> PermissionsUrlsSetUnrestrictedModeResult: + "Toggles the runtime's URL-permission policy between unrestricted and restricted modes.\n\nArgs:\n params: Whether the URL-permission policy should run in unrestricted mode.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsUrlsSetUnrestrictedModeResult.from_dict(await self._client.request("session.permissions.urls.setUnrestrictedMode", params_dict, **_timeout_kwargs(timeout))) + class PermissionsApi: def __init__(self, client: "JsonRpcClient", session_id: str): self._client = client self._session_id = session_id + self.paths = PermissionsPathsApi(client, session_id) + self.urls = PermissionsUrlsApi(client, session_id) + + async def configure(self, params: PermissionsConfigureParams, *, timeout: float | None = None) -> PermissionsConfigureResult: + "Replaces selected permission policy fields (rules, paths, URLs, exclusions, allow-all flags) on the session.\n\nArgs:\n params: Patch of permission policy fields to apply (omit a field to leave it unchanged).\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsConfigureResult.from_dict(await self._client.request("session.permissions.configure", params_dict, **_timeout_kwargs(timeout))) async def handle_pending_permission_request(self, params: PermissionDecisionRequest, *, timeout: float | None = None) -> PermissionRequestResult: "Provides a decision for a pending tool permission request.\n\nArgs:\n params: Pending permission request ID and the decision to apply (approve/reject and scope).\n\nReturns:\n Indicates whether the permission decision was applied; false when the request was already resolved." @@ -8846,16 +16379,77 @@ async def handle_pending_permission_request(self, params: PermissionDecisionRequ params_dict["sessionId"] = self._session_id return PermissionRequestResult.from_dict(await self._client.request("session.permissions.handlePendingPermissionRequest", params_dict, **_timeout_kwargs(timeout))) + async def pending_requests(self, *, timeout: float | None = None) -> PendingPermissionRequestList: + "Reconstructs the set of pending tool permission requests from the session's event history.\n\nReturns:\n List of pending permission requests reconstructed from event history." + return PendingPermissionRequestList.from_dict(await self._client.request("session.permissions.pendingRequests", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def set_approve_all(self, params: PermissionsSetApproveAllRequest, *, timeout: float | None = None) -> PermissionsSetApproveAllResult: - "Enables or disables automatic approval of tool permission requests for the session.\n\nArgs:\n params: Whether to auto-approve all tool permission requests for the rest of the session.\n\nReturns:\n Indicates whether the operation succeeded." + "Enables or disables automatic approval of tool permission requests for the session.\n\nArgs:\n params: Allow-all toggle for tool permission requests, with an optional telemetry source.\n\nReturns:\n Indicates whether the operation succeeded." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return PermissionsSetApproveAllResult.from_dict(await self._client.request("session.permissions.setApproveAll", params_dict, **_timeout_kwargs(timeout))) + async def modify_rules(self, params: PermissionsModifyRulesParams, *, timeout: float | None = None) -> PermissionsModifyRulesResult: + "Adds or removes session-scoped or location-scoped permission rules.\n\nArgs:\n params: Scope and add/remove instructions for modifying session- or location-scoped permission rules.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsModifyRulesResult.from_dict(await self._client.request("session.permissions.modifyRules", params_dict, **_timeout_kwargs(timeout))) + + async def set_required(self, params: PermissionsSetRequiredRequest, *, timeout: float | None = None) -> PermissionsSetRequiredResult: + "Sets whether the client wants permission prompts bridged into session events.\n\nArgs:\n params: Toggles whether permission prompts should be bridged into session events for this client.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsSetRequiredResult.from_dict(await self._client.request("session.permissions.setRequired", params_dict, **_timeout_kwargs(timeout))) + async def reset_session_approvals(self, *, timeout: float | None = None) -> PermissionsResetSessionApprovalsResult: "Clears session-scoped tool permission approvals.\n\nReturns:\n Indicates whether the operation succeeded." return PermissionsResetSessionApprovalsResult.from_dict(await self._client.request("session.permissions.resetSessionApprovals", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + async def notify_prompt_shown(self, params: PermissionPromptShownNotification, *, timeout: float | None = None) -> PermissionsNotifyPromptShownResult: + "Notifies the runtime that a permission prompt UI has been shown to the user.\n\nArgs:\n params: Notification payload describing the permission prompt that the client just rendered.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return PermissionsNotifyPromptShownResult.from_dict(await self._client.request("session.permissions.notifyPromptShown", params_dict, **_timeout_kwargs(timeout))) + + +# Experimental: this API group is experimental and may change or be removed. +class MetadataApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def snapshot(self, *, timeout: float | None = None) -> SessionMetadataSnapshot: + "Returns a snapshot of the session's identifying metadata, mode, agent, and remote info.\n\nReturns:\n Point-in-time snapshot of slow-changing session identifier and state fields" + return SessionMetadataSnapshot.from_dict(await self._client.request("session.metadata.snapshot", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def is_processing(self, *, timeout: float | None = None) -> MetadataIsProcessingResult: + "Reports whether the local session is currently processing user/agent messages.\n\nReturns:\n Indicates whether the local session is currently processing a turn or background continuation." + return MetadataIsProcessingResult.from_dict(await self._client.request("session.metadata.isProcessing", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def context_info(self, params: MetadataContextInfoRequest, *, timeout: float | None = None) -> MetadataContextInfoResult: + "Returns the token breakdown for the session's current context window for a given model.\n\nArgs:\n params: Model identifier and token limits used to compute the context-info breakdown.\n\nReturns:\n Token breakdown for the session's current context window, or null if uninitialized." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MetadataContextInfoResult.from_dict(await self._client.request("session.metadata.contextInfo", params_dict, **_timeout_kwargs(timeout))) + + async def record_context_change(self, params: MetadataRecordContextChangeRequest, *, timeout: float | None = None) -> MetadataRecordContextChangeResult: + "Records a working-directory/git context change and emits a `session.context_changed` event.\n\nArgs:\n params: Updated working-directory/git context to record on the session.\n\nReturns:\n Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode)." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MetadataRecordContextChangeResult.from_dict(await self._client.request("session.metadata.recordContextChange", params_dict, **_timeout_kwargs(timeout))) + + async def set_working_directory(self, params: MetadataSetWorkingDirectoryRequest, *, timeout: float | None = None) -> MetadataSetWorkingDirectoryResult: + "Updates the session's recorded working directory.\n\nArgs:\n params: Absolute path to set as the session's new working directory.\n\nReturns:\n Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MetadataSetWorkingDirectoryResult.from_dict(await self._client.request("session.metadata.setWorkingDirectory", params_dict, **_timeout_kwargs(timeout))) + + async def recompute_context_tokens(self, params: MetadataRecomputeContextTokensRequest, *, timeout: float | None = None) -> MetadataRecomputeContextTokensResult: + "Re-tokenizes the session's existing messages against a model and returns aggregate token totals.\n\nArgs:\n params: Model identifier to use when re-tokenizing the session's existing messages.\n\nReturns:\n Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return MetadataRecomputeContextTokensResult.from_dict(await self._client.request("session.metadata.recomputeContextTokens", params_dict, **_timeout_kwargs(timeout))) + class ShellApi: def __init__(self, client: "JsonRpcClient", session_id: str): @@ -8882,7 +16476,7 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self._session_id = session_id async def compact(self, *, timeout: float | None = None) -> HistoryCompactResult: - "Compacts the session history to reduce context usage.\n\nReturns:\n Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown." + "Compacts the session history to reduce context usage.\n\nReturns:\n Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown." return HistoryCompactResult.from_dict(await self._client.request("session.history.compact", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) async def truncate(self, params: HistoryTruncateRequest, *, timeout: float | None = None) -> HistoryTruncateResult: @@ -8891,6 +16485,66 @@ async def truncate(self, params: HistoryTruncateRequest, *, timeout: float | Non params_dict["sessionId"] = self._session_id return HistoryTruncateResult.from_dict(await self._client.request("session.history.truncate", params_dict, **_timeout_kwargs(timeout))) + async def cancel_background_compaction(self, *, timeout: float | None = None) -> HistoryCancelBackgroundCompactionResult: + "Cancels any in-progress background compaction on a local session.\n\nReturns:\n Indicates whether an in-progress background compaction was cancelled." + return HistoryCancelBackgroundCompactionResult.from_dict(await self._client.request("session.history.cancelBackgroundCompaction", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def abort_manual_compaction(self, *, timeout: float | None = None) -> HistoryAbortManualCompactionResult: + "Aborts any in-progress manual compaction on a local session.\n\nReturns:\n Indicates whether an in-progress manual compaction was aborted." + return HistoryAbortManualCompactionResult.from_dict(await self._client.request("session.history.abortManualCompaction", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def summarize_for_handoff(self, *, timeout: float | None = None) -> HistorySummarizeForHandoffResult: + "Produces a markdown summary of the session's conversation context for hand-off scenarios.\n\nReturns:\n Markdown summary of the conversation context (empty when not available)." + return HistorySummarizeForHandoffResult.from_dict(await self._client.request("session.history.summarizeForHandoff", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + +# Experimental: this API group is experimental and may change or be removed. +class QueueApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def pending_items(self, *, timeout: float | None = None) -> QueuePendingItemsResult: + "Returns the local session's pending user-facing queued items and steering messages.\n\nReturns:\n Snapshot of the session's pending queued items and immediate-steering messages." + return QueuePendingItemsResult.from_dict(await self._client.request("session.queue.pendingItems", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def remove_most_recent(self, *, timeout: float | None = None) -> QueueRemoveMostRecentResult: + "Removes the most recently queued user-facing item (LIFO).\n\nReturns:\n Indicates whether a user-facing pending item was removed." + return QueueRemoveMostRecentResult.from_dict(await self._client.request("session.queue.removeMostRecent", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def clear(self, *, timeout: float | None = None) -> None: + "Clears all pending queued items on the local session." + await self._client.request("session.queue.clear", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) + + +# Experimental: this API group is experimental and may change or be removed. +class EventLogApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def read(self, params: EventLogReadRequest, *, timeout: float | None = None) -> EventsReadResult: + "Reads a batch of session events from a cursor, optionally waiting for new events.\n\nArgs:\n params: Cursor, batch size, and optional long-poll/filter parameters for reading session events.\n\nReturns:\n Batch of session events returned by a read, with cursor and continuation metadata." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return EventsReadResult.from_dict(await self._client.request("session.eventLog.read", params_dict, **_timeout_kwargs(timeout))) + + async def tail(self, *, timeout: float | None = None) -> EventLogTailResult: + "Returns a snapshot of the current tail cursor without consuming events.\n\nReturns:\n Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session)." + return EventLogTailResult.from_dict(await self._client.request("session.eventLog.tail", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def register_interest(self, params: RegisterEventInterestParams, *, timeout: float | None = None) -> RegisterEventInterestResult: + "Registers consumer interest in an event type for runtime gating purposes.\n\nArgs:\n params: Event type to register consumer interest for, used by runtime gating logic.\n\nReturns:\n Opaque handle representing an event-type interest registration." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return RegisterEventInterestResult.from_dict(await self._client.request("session.eventLog.registerInterest", params_dict, **_timeout_kwargs(timeout))) + + async def release_interest(self, params: ReleaseEventInterestParams, *, timeout: float | None = None) -> EventLogReleaseInterestResult: + "Releases a consumer's previously-registered interest in an event type.\n\nArgs:\n params: Opaque handle previously returned by `registerInterest` to release.\n\nReturns:\n Indicates whether the operation succeeded." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return EventLogReleaseInterestResult.from_dict(await self._client.request("session.eventLog.releaseInterest", params_dict, **_timeout_kwargs(timeout))) + # Experimental: this API group is experimental and may change or be removed. class UsageApi: @@ -8919,6 +16573,29 @@ async def disable(self, *, timeout: float | None = None) -> None: "Disables remote session export and steering." await self._client.request("session.remote.disable", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) + async def notify_steerable_changed(self, params: RemoteNotifySteerableChangedRequest, *, timeout: float | None = None) -> RemoteNotifySteerableChangedResult: + "Persists a remote-steerability change emitted by the host as a session event.\n\nArgs:\n params: New remote-steerability state to persist as a `session.remote_steerable_changed` event.\n\nReturns:\n Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return RemoteNotifySteerableChangedResult.from_dict(await self._client.request("session.remote.notifySteerableChanged", params_dict, **_timeout_kwargs(timeout))) + + +# Experimental: this API group is experimental and may change or be removed. +class ScheduleApi: + def __init__(self, client: "JsonRpcClient", session_id: str): + self._client = client + self._session_id = session_id + + async def list(self, *, timeout: float | None = None) -> ScheduleList: + "Lists the session's currently active scheduled prompts.\n\nReturns:\n Snapshot of the currently active recurring prompts for this session." + return ScheduleList.from_dict(await self._client.request("session.schedule.list", {"sessionId": self._session_id}, **_timeout_kwargs(timeout))) + + async def stop(self, params: ScheduleStopRequest, *, timeout: float | None = None) -> ScheduleStopResult: + "Removes a scheduled prompt by id.\n\nArgs:\n params: Identifier of the scheduled prompt to remove.\n\nReturns:\n Remove a scheduled prompt by id. The result entry is omitted if the id was unknown." + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return ScheduleStopResult.from_dict(await self._client.request("session.schedule.stop", params_dict, **_timeout_kwargs(timeout))) + class SessionRpc: """Typed session-scoped RPC methods.""" @@ -8938,22 +16615,47 @@ def __init__(self, client: "JsonRpcClient", session_id: str): self.skills = SkillsApi(client, session_id) self.mcp = McpApi(client, session_id) self.plugins = PluginsApi(client, session_id) + self.options = OptionsApi(client, session_id) + self.lsp = LspApi(client, session_id) self.extensions = ExtensionsApi(client, session_id) self.tools = ToolsApi(client, session_id) self.commands = CommandsApi(client, session_id) + self.telemetry = TelemetryApi(client, session_id) self.ui = UiApi(client, session_id) self.permissions = PermissionsApi(client, session_id) + self.metadata = MetadataApi(client, session_id) self.shell = ShellApi(client, session_id) self.history = HistoryApi(client, session_id) + self.queue = QueueApi(client, session_id) + self.event_log = EventLogApi(client, session_id) self.usage = UsageApi(client, session_id) self.remote = RemoteApi(client, session_id) + self.schedule = ScheduleApi(client, session_id) async def suspend(self, *, timeout: float | None = None) -> None: "Suspends the session while preserving persisted state for later resume." await self._client.request("session.suspend", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)) + async def send(self, params: SendRequest, *, timeout: float | None = None) -> SendResult: + "Sends a user message to the session and returns its message ID.\n\nArgs:\n params: Parameters for sending a user message to the session\n\nReturns:\n Result of sending a user message" + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return SendResult.from_dict(await self._client.request("session.send", params_dict, **_timeout_kwargs(timeout))) + + async def abort(self, params: AbortRequest, *, timeout: float | None = None) -> AbortResult: + "Aborts the current agent turn.\n\nArgs:\n params: Parameters for aborting the current turn\n\nReturns:\n Result of aborting the current turn" + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + return AbortResult.from_dict(await self._client.request("session.abort", params_dict, **_timeout_kwargs(timeout))) + + async def shutdown(self, params: ShutdownRequest, *, timeout: float | None = None) -> None: + "Shuts down the session and persists its final state. Awaits any deferred sessionEnd hooks before resolving so user-supplied hook scripts complete before the runtime tears down.\n\nArgs:\n params: Parameters for shutting down the session" + params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} + params_dict["sessionId"] = self._session_id + await self._client.request("session.shutdown", params_dict, **_timeout_kwargs(timeout)) + async def log(self, params: LogRequest, *, timeout: float | None = None) -> LogResult: - "Emits a user-visible session log event.\n\nArgs:\n params: Message text, optional severity level, persistence flag, and optional follow-up URL.\n\nReturns:\n Identifier of the session event that was emitted for the log message." + "Emits a user-visible session log event.\n\nArgs:\n params: Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip.\n\nReturns:\n Identifier of the session event that was emitted for the log message." params_dict: dict[str, Any] = {k: v for k, v in params.to_dict().items() if v is not None} params_dict["sessionId"] = self._session_id return LogResult.from_dict(await self._client.request("session.log", params_dict, **_timeout_kwargs(timeout))) diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index 4f1b0bc03..2cae80644 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -325,7 +325,7 @@ class AssistantMessageData: encrypted_content: str | None = None interaction_id: str | None = None model: str | None = None - output_tokens: float | None = None + output_tokens: int | None = None # Deprecated: this field is deprecated. parent_tool_call_id: str | None = None phase: str | None = None @@ -345,7 +345,7 @@ def from_dict(obj: Any) -> "AssistantMessageData": encrypted_content = from_union([from_none, from_str], obj.get("encryptedContent")) interaction_id = from_union([from_none, from_str], obj.get("interactionId")) model = from_union([from_none, from_str], obj.get("model")) - output_tokens = from_union([from_none, from_float], obj.get("outputTokens")) + output_tokens = from_union([from_none, from_int], obj.get("outputTokens")) parent_tool_call_id = from_union([from_none, from_str], obj.get("parentToolCallId")) phase = from_union([from_none, from_str], obj.get("phase")) reasoning_opaque = from_union([from_none, from_str], obj.get("reasoningOpaque")) @@ -386,7 +386,7 @@ def to_dict(self) -> dict: if self.model is not None: result["model"] = from_union([from_none, from_str], self.model) if self.output_tokens is not None: - result["outputTokens"] = from_union([from_none, to_float], self.output_tokens) + result["outputTokens"] = from_union([from_none, to_int], self.output_tokens) if self.parent_tool_call_id is not None: result["parentToolCallId"] = from_union([from_none, from_str], self.parent_tool_call_id) if self.phase is not None: @@ -559,19 +559,19 @@ def to_dict(self) -> dict: @dataclass class AssistantStreamingDeltaData: "Streaming response progress with cumulative byte count" - total_response_size_bytes: float + total_response_size_bytes: int @staticmethod def from_dict(obj: Any) -> "AssistantStreamingDeltaData": assert isinstance(obj, dict) - total_response_size_bytes = from_float(obj.get("totalResponseSizeBytes")) + total_response_size_bytes = from_int(obj.get("totalResponseSizeBytes")) return AssistantStreamingDeltaData( total_response_size_bytes=total_response_size_bytes, ) def to_dict(self) -> dict: result: dict = {} - result["totalResponseSizeBytes"] = to_float(self.total_response_size_bytes) + result["totalResponseSizeBytes"] = to_int(self.total_response_size_bytes) return result @@ -622,13 +622,13 @@ def to_dict(self) -> dict: class AssistantUsageCopilotUsage: "Per-request cost and usage data from the CAPI copilot_usage response field" token_details: list[AssistantUsageCopilotUsageTokenDetail] - total_nano_aiu: float + total_nano_aiu: int @staticmethod def from_dict(obj: Any) -> "AssistantUsageCopilotUsage": assert isinstance(obj, dict) token_details = from_list(AssistantUsageCopilotUsageTokenDetail.from_dict, obj.get("tokenDetails")) - total_nano_aiu = from_float(obj.get("totalNanoAiu")) + total_nano_aiu = from_int(obj.get("totalNanoAiu")) return AssistantUsageCopilotUsage( token_details=token_details, total_nano_aiu=total_nano_aiu, @@ -637,24 +637,24 @@ def from_dict(obj: Any) -> "AssistantUsageCopilotUsage": def to_dict(self) -> dict: result: dict = {} result["tokenDetails"] = from_list(lambda x: to_class(AssistantUsageCopilotUsageTokenDetail, x), self.token_details) - result["totalNanoAiu"] = to_float(self.total_nano_aiu) + result["totalNanoAiu"] = to_int(self.total_nano_aiu) return result @dataclass class AssistantUsageCopilotUsageTokenDetail: "Token usage detail for a single billing category" - batch_size: float - cost_per_batch: float - token_count: float + batch_size: int + cost_per_batch: int + token_count: int token_type: str @staticmethod 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")) + batch_size = from_int(obj.get("batchSize")) + cost_per_batch = from_int(obj.get("costPerBatch")) + token_count = from_int(obj.get("tokenCount")) token_type = from_str(obj.get("tokenType")) return AssistantUsageCopilotUsageTokenDetail( batch_size=batch_size, @@ -665,9 +665,9 @@ def from_dict(obj: Any) -> "AssistantUsageCopilotUsageTokenDetail": def to_dict(self) -> dict: result: dict = {} - result["batchSize"] = to_float(self.batch_size) - result["costPerBatch"] = to_float(self.cost_per_batch) - result["tokenCount"] = to_float(self.token_count) + result["batchSize"] = to_int(self.batch_size) + result["costPerBatch"] = to_int(self.cost_per_batch) + result["tokenCount"] = to_int(self.token_count) result["tokenType"] = from_str(self.token_type) return result @@ -678,21 +678,21 @@ class AssistantUsageData: model: str api_call_id: str | None = None api_endpoint: AssistantUsageApiEndpoint | None = None - cache_read_tokens: float | None = None - cache_write_tokens: float | None = None + cache_read_tokens: int | None = None + cache_write_tokens: int | None = None copilot_usage: AssistantUsageCopilotUsage | None = None cost: float | None = None duration: timedelta | None = None initiator: str | None = None - input_tokens: float | None = None + input_tokens: int | None = None inter_token_latency: timedelta | None = None - output_tokens: float | None = None + output_tokens: int | None = None # Deprecated: this field is deprecated. parent_tool_call_id: str | None = None provider_call_id: str | None = None quota_snapshots: dict[str, AssistantUsageQuotaSnapshot] | None = None reasoning_effort: str | None = None - reasoning_tokens: float | None = None + reasoning_tokens: int | None = None ttft: timedelta | None = None @staticmethod @@ -701,20 +701,20 @@ def from_dict(obj: Any) -> "AssistantUsageData": model = from_str(obj.get("model")) api_call_id = from_union([from_none, from_str], obj.get("apiCallId")) api_endpoint = from_union([from_none, lambda x: parse_enum(AssistantUsageApiEndpoint, x)], obj.get("apiEndpoint")) - cache_read_tokens = from_union([from_none, from_float], obj.get("cacheReadTokens")) - cache_write_tokens = from_union([from_none, from_float], obj.get("cacheWriteTokens")) + cache_read_tokens = from_union([from_none, from_int], obj.get("cacheReadTokens")) + cache_write_tokens = from_union([from_none, from_int], obj.get("cacheWriteTokens")) copilot_usage = from_union([from_none, AssistantUsageCopilotUsage.from_dict], obj.get("copilotUsage")) cost = from_union([from_none, from_float], obj.get("cost")) duration = from_union([from_none, from_timedelta], obj.get("duration")) initiator = from_union([from_none, from_str], obj.get("initiator")) - input_tokens = from_union([from_none, from_float], obj.get("inputTokens")) + input_tokens = from_union([from_none, from_int], obj.get("inputTokens")) inter_token_latency = from_union([from_none, from_timedelta], obj.get("interTokenLatencyMs")) - output_tokens = from_union([from_none, from_float], obj.get("outputTokens")) + output_tokens = from_union([from_none, from_int], obj.get("outputTokens")) parent_tool_call_id = from_union([from_none, from_str], obj.get("parentToolCallId")) provider_call_id = from_union([from_none, from_str], obj.get("providerCallId")) quota_snapshots = from_union([from_none, lambda x: from_dict(AssistantUsageQuotaSnapshot.from_dict, x)], obj.get("quotaSnapshots")) reasoning_effort = from_union([from_none, from_str], obj.get("reasoningEffort")) - reasoning_tokens = from_union([from_none, from_float], obj.get("reasoningTokens")) + reasoning_tokens = from_union([from_none, from_int], obj.get("reasoningTokens")) ttft = from_union([from_none, from_timedelta], obj.get("ttftMs")) return AssistantUsageData( model=model, @@ -745,23 +745,23 @@ def to_dict(self) -> dict: if self.api_endpoint is not None: result["apiEndpoint"] = from_union([from_none, lambda x: to_enum(AssistantUsageApiEndpoint, x)], self.api_endpoint) if self.cache_read_tokens is not None: - result["cacheReadTokens"] = from_union([from_none, to_float], self.cache_read_tokens) + result["cacheReadTokens"] = from_union([from_none, to_int], self.cache_read_tokens) if self.cache_write_tokens is not None: - result["cacheWriteTokens"] = from_union([from_none, to_float], self.cache_write_tokens) + result["cacheWriteTokens"] = from_union([from_none, to_int], self.cache_write_tokens) if self.copilot_usage is not None: result["copilotUsage"] = from_union([from_none, lambda x: to_class(AssistantUsageCopilotUsage, x)], self.copilot_usage) if self.cost is not None: result["cost"] = from_union([from_none, to_float], self.cost) if self.duration is not None: - result["duration"] = from_union([from_none, to_timedelta], self.duration) + result["duration"] = from_union([from_none, to_timedelta_int], self.duration) if self.initiator is not None: result["initiator"] = from_union([from_none, from_str], self.initiator) if self.input_tokens is not None: - result["inputTokens"] = from_union([from_none, to_float], self.input_tokens) + result["inputTokens"] = from_union([from_none, to_int], self.input_tokens) if self.inter_token_latency is not None: result["interTokenLatencyMs"] = from_union([from_none, to_timedelta], self.inter_token_latency) if self.output_tokens is not None: - result["outputTokens"] = from_union([from_none, to_float], self.output_tokens) + result["outputTokens"] = from_union([from_none, to_int], self.output_tokens) if self.parent_tool_call_id is not None: result["parentToolCallId"] = from_union([from_none, from_str], self.parent_tool_call_id) if self.provider_call_id is not None: @@ -771,34 +771,34 @@ def to_dict(self) -> dict: if self.reasoning_effort is not None: result["reasoningEffort"] = from_union([from_none, from_str], self.reasoning_effort) if self.reasoning_tokens is not None: - result["reasoningTokens"] = from_union([from_none, to_float], self.reasoning_tokens) + result["reasoningTokens"] = from_union([from_none, to_int], self.reasoning_tokens) if self.ttft is not None: - result["ttftMs"] = from_union([from_none, to_timedelta], self.ttft) + result["ttftMs"] = from_union([from_none, to_timedelta_int], self.ttft) return result @dataclass class AssistantUsageQuotaSnapshot: "Schema for the `AssistantUsageQuotaSnapshot` type." - entitlement_requests: float + entitlement_requests: int is_unlimited_entitlement: bool overage: float overage_allowed_with_exhausted_quota: bool remaining_percentage: float usage_allowed_with_exhausted_quota: bool - used_requests: float + used_requests: int reset_date: datetime | None = None @staticmethod def from_dict(obj: Any) -> "AssistantUsageQuotaSnapshot": assert isinstance(obj, dict) - entitlement_requests = from_float(obj.get("entitlementRequests")) + entitlement_requests = from_int(obj.get("entitlementRequests")) is_unlimited_entitlement = from_bool(obj.get("isUnlimitedEntitlement")) overage = from_float(obj.get("overage")) overage_allowed_with_exhausted_quota = from_bool(obj.get("overageAllowedWithExhaustedQuota")) remaining_percentage = from_float(obj.get("remainingPercentage")) usage_allowed_with_exhausted_quota = from_bool(obj.get("usageAllowedWithExhaustedQuota")) - used_requests = from_float(obj.get("usedRequests")) + used_requests = from_int(obj.get("usedRequests")) reset_date = from_union([from_none, from_datetime], obj.get("resetDate")) return AssistantUsageQuotaSnapshot( entitlement_requests=entitlement_requests, @@ -813,13 +813,13 @@ def from_dict(obj: Any) -> "AssistantUsageQuotaSnapshot": def to_dict(self) -> dict: result: dict = {} - result["entitlementRequests"] = to_float(self.entitlement_requests) + result["entitlementRequests"] = to_int(self.entitlement_requests) result["isUnlimitedEntitlement"] = from_bool(self.is_unlimited_entitlement) result["overage"] = to_float(self.overage) result["overageAllowedWithExhaustedQuota"] = from_bool(self.overage_allowed_with_exhausted_quota) result["remainingPercentage"] = to_float(self.remaining_percentage) result["usageAllowedWithExhaustedQuota"] = from_bool(self.usage_allowed_with_exhausted_quota) - result["usedRequests"] = to_float(self.used_requests) + result["usedRequests"] = to_int(self.used_requests) if self.reset_date is not None: result["resetDate"] = from_union([from_none, to_datetime], self.reset_date) return result @@ -853,14 +853,14 @@ class AutoModeSwitchRequestedData: "Auto mode switch request notification requiring user approval" request_id: str error_code: str | None = None - retry_after_seconds: float | None = None + retry_after_seconds: timedelta | None = None @staticmethod def from_dict(obj: Any) -> "AutoModeSwitchRequestedData": assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) error_code = from_union([from_none, from_str], obj.get("errorCode")) - retry_after_seconds = from_union([from_none, from_float], obj.get("retryAfterSeconds")) + retry_after_seconds = from_union([from_none, from_timedelta], obj.get("retryAfterSeconds")) return AutoModeSwitchRequestedData( request_id=request_id, error_code=error_code, @@ -873,7 +873,7 @@ def to_dict(self) -> dict: if self.error_code is not None: result["errorCode"] = from_union([from_none, from_str], self.error_code) if self.retry_after_seconds is not None: - result["retryAfterSeconds"] = from_union([from_none, to_float], self.retry_after_seconds) + result["retryAfterSeconds"] = from_union([from_none, to_timedelta_int], self.retry_after_seconds) return result @@ -1036,24 +1036,24 @@ def to_dict(self) -> dict: @dataclass class CompactionCompleteCompactionTokensUsed: "Token usage breakdown for the compaction LLM call (aligned with assistant.usage format)" - cache_read_tokens: float | None = None - cache_write_tokens: float | None = None + cache_read_tokens: int | None = None + cache_write_tokens: int | None = None copilot_usage: CompactionCompleteCompactionTokensUsedCopilotUsage | None = None duration: timedelta | None = None - input_tokens: float | None = None + input_tokens: int | None = None model: str | None = None - output_tokens: float | None = None + output_tokens: int | None = None @staticmethod def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsed": assert isinstance(obj, dict) - cache_read_tokens = from_union([from_none, from_float], obj.get("cacheReadTokens")) - cache_write_tokens = from_union([from_none, from_float], obj.get("cacheWriteTokens")) + cache_read_tokens = from_union([from_none, from_int], obj.get("cacheReadTokens")) + cache_write_tokens = from_union([from_none, from_int], obj.get("cacheWriteTokens")) copilot_usage = from_union([from_none, CompactionCompleteCompactionTokensUsedCopilotUsage.from_dict], obj.get("copilotUsage")) duration = from_union([from_none, from_timedelta], obj.get("duration")) - input_tokens = from_union([from_none, from_float], obj.get("inputTokens")) + input_tokens = from_union([from_none, from_int], obj.get("inputTokens")) model = from_union([from_none, from_str], obj.get("model")) - output_tokens = from_union([from_none, from_float], obj.get("outputTokens")) + output_tokens = from_union([from_none, from_int], obj.get("outputTokens")) return CompactionCompleteCompactionTokensUsed( cache_read_tokens=cache_read_tokens, cache_write_tokens=cache_write_tokens, @@ -1067,19 +1067,19 @@ def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsed": def to_dict(self) -> dict: result: dict = {} if self.cache_read_tokens is not None: - result["cacheReadTokens"] = from_union([from_none, to_float], self.cache_read_tokens) + result["cacheReadTokens"] = from_union([from_none, to_int], self.cache_read_tokens) if self.cache_write_tokens is not None: - result["cacheWriteTokens"] = from_union([from_none, to_float], self.cache_write_tokens) + result["cacheWriteTokens"] = from_union([from_none, to_int], self.cache_write_tokens) if self.copilot_usage is not None: result["copilotUsage"] = from_union([from_none, lambda x: to_class(CompactionCompleteCompactionTokensUsedCopilotUsage, x)], self.copilot_usage) if self.duration is not None: - result["duration"] = from_union([from_none, to_timedelta], self.duration) + result["duration"] = from_union([from_none, to_timedelta_int], self.duration) if self.input_tokens is not None: - result["inputTokens"] = from_union([from_none, to_float], self.input_tokens) + result["inputTokens"] = from_union([from_none, to_int], self.input_tokens) if self.model is not None: result["model"] = from_union([from_none, from_str], self.model) if self.output_tokens is not None: - result["outputTokens"] = from_union([from_none, to_float], self.output_tokens) + result["outputTokens"] = from_union([from_none, to_int], self.output_tokens) return result @@ -1087,13 +1087,13 @@ def to_dict(self) -> dict: class CompactionCompleteCompactionTokensUsedCopilotUsage: "Per-request cost and usage data from the CAPI copilot_usage response field" token_details: list[CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail] - total_nano_aiu: float + total_nano_aiu: int @staticmethod def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsedCopilotUsage": assert isinstance(obj, dict) token_details = from_list(CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail.from_dict, obj.get("tokenDetails")) - total_nano_aiu = from_float(obj.get("totalNanoAiu")) + total_nano_aiu = from_int(obj.get("totalNanoAiu")) return CompactionCompleteCompactionTokensUsedCopilotUsage( token_details=token_details, total_nano_aiu=total_nano_aiu, @@ -1102,24 +1102,24 @@ def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsedCopilotUsage": def to_dict(self) -> dict: result: dict = {} result["tokenDetails"] = from_list(lambda x: to_class(CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail, x), self.token_details) - result["totalNanoAiu"] = to_float(self.total_nano_aiu) + result["totalNanoAiu"] = to_int(self.total_nano_aiu) return result @dataclass class CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail: "Token usage detail for a single billing category" - batch_size: float - cost_per_batch: float - token_count: float + batch_size: int + cost_per_batch: int + token_count: int token_type: str @staticmethod def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail": 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")) + batch_size = from_int(obj.get("batchSize")) + cost_per_batch = from_int(obj.get("costPerBatch")) + token_count = from_int(obj.get("tokenCount")) token_type = from_str(obj.get("tokenType")) return CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail( batch_size=batch_size, @@ -1130,9 +1130,9 @@ def from_dict(obj: Any) -> "CompactionCompleteCompactionTokensUsedCopilotUsageTo def to_dict(self) -> dict: result: dict = {} - result["batchSize"] = to_float(self.batch_size) - result["costPerBatch"] = to_float(self.cost_per_batch) - result["tokenCount"] = to_float(self.token_count) + result["batchSize"] = to_int(self.batch_size) + result["costPerBatch"] = to_int(self.cost_per_batch) + result["tokenCount"] = to_int(self.token_count) result["tokenType"] = from_str(self.token_type) return result @@ -1786,7 +1786,7 @@ def to_dict(self) -> dict: if self.api_call_id is not None: result["apiCallId"] = from_union([from_none, from_str], self.api_call_id) if self.duration is not None: - result["durationMs"] = from_union([from_none, to_timedelta], self.duration) + result["durationMs"] = from_union([from_none, to_timedelta_int], self.duration) if self.error_message is not None: result["errorMessage"] = from_union([from_none, from_str], self.error_message) if self.initiator is not None: @@ -2402,39 +2402,39 @@ def to_dict(self) -> dict: class SessionCompactionCompleteData: "Conversation compaction results including success status, metrics, and optional error details" success: bool - checkpoint_number: float | None = None + checkpoint_number: int | None = None checkpoint_path: str | None = None compaction_tokens_used: CompactionCompleteCompactionTokensUsed | None = None - conversation_tokens: float | None = None + conversation_tokens: int | None = None error: str | None = None - messages_removed: float | None = None - post_compaction_tokens: float | None = None - pre_compaction_messages_length: float | None = None - pre_compaction_tokens: float | None = None + messages_removed: int | None = None + post_compaction_tokens: int | None = None + pre_compaction_messages_length: int | None = None + pre_compaction_tokens: int | None = None request_id: str | None = None summary_content: str | None = None - system_tokens: float | None = None - tokens_removed: float | None = None - tool_definitions_tokens: float | None = None + system_tokens: int | None = None + tokens_removed: int | None = None + tool_definitions_tokens: int | None = None @staticmethod def from_dict(obj: Any) -> "SessionCompactionCompleteData": assert isinstance(obj, dict) success = from_bool(obj.get("success")) - checkpoint_number = from_union([from_none, from_float], obj.get("checkpointNumber")) + checkpoint_number = from_union([from_none, from_int], obj.get("checkpointNumber")) checkpoint_path = from_union([from_none, from_str], obj.get("checkpointPath")) compaction_tokens_used = from_union([from_none, CompactionCompleteCompactionTokensUsed.from_dict], obj.get("compactionTokensUsed")) - conversation_tokens = from_union([from_none, from_float], obj.get("conversationTokens")) + conversation_tokens = from_union([from_none, from_int], obj.get("conversationTokens")) error = from_union([from_none, from_str], obj.get("error")) - messages_removed = from_union([from_none, from_float], obj.get("messagesRemoved")) - post_compaction_tokens = from_union([from_none, from_float], obj.get("postCompactionTokens")) - pre_compaction_messages_length = from_union([from_none, from_float], obj.get("preCompactionMessagesLength")) - pre_compaction_tokens = from_union([from_none, from_float], obj.get("preCompactionTokens")) + messages_removed = from_union([from_none, from_int], obj.get("messagesRemoved")) + post_compaction_tokens = from_union([from_none, from_int], obj.get("postCompactionTokens")) + pre_compaction_messages_length = from_union([from_none, from_int], obj.get("preCompactionMessagesLength")) + pre_compaction_tokens = from_union([from_none, from_int], obj.get("preCompactionTokens")) request_id = from_union([from_none, from_str], obj.get("requestId")) summary_content = from_union([from_none, from_str], obj.get("summaryContent")) - system_tokens = from_union([from_none, from_float], obj.get("systemTokens")) - tokens_removed = from_union([from_none, from_float], obj.get("tokensRemoved")) - tool_definitions_tokens = from_union([from_none, from_float], obj.get("toolDefinitionsTokens")) + system_tokens = from_union([from_none, from_int], obj.get("systemTokens")) + tokens_removed = from_union([from_none, from_int], obj.get("tokensRemoved")) + tool_definitions_tokens = from_union([from_none, from_int], obj.get("toolDefinitionsTokens")) return SessionCompactionCompleteData( success=success, checkpoint_number=checkpoint_number, @@ -2457,49 +2457,49 @@ def to_dict(self) -> dict: result: dict = {} result["success"] = from_bool(self.success) if self.checkpoint_number is not None: - result["checkpointNumber"] = from_union([from_none, to_float], self.checkpoint_number) + result["checkpointNumber"] = from_union([from_none, to_int], self.checkpoint_number) if self.checkpoint_path is not None: result["checkpointPath"] = from_union([from_none, from_str], self.checkpoint_path) if self.compaction_tokens_used is not None: result["compactionTokensUsed"] = from_union([from_none, lambda x: to_class(CompactionCompleteCompactionTokensUsed, x)], self.compaction_tokens_used) if self.conversation_tokens is not None: - result["conversationTokens"] = from_union([from_none, to_float], self.conversation_tokens) + result["conversationTokens"] = from_union([from_none, to_int], self.conversation_tokens) if self.error is not None: result["error"] = from_union([from_none, from_str], self.error) if self.messages_removed is not None: - result["messagesRemoved"] = from_union([from_none, to_float], self.messages_removed) + result["messagesRemoved"] = from_union([from_none, to_int], self.messages_removed) if self.post_compaction_tokens is not None: - result["postCompactionTokens"] = from_union([from_none, to_float], self.post_compaction_tokens) + result["postCompactionTokens"] = from_union([from_none, to_int], self.post_compaction_tokens) if self.pre_compaction_messages_length is not None: - result["preCompactionMessagesLength"] = from_union([from_none, to_float], self.pre_compaction_messages_length) + result["preCompactionMessagesLength"] = from_union([from_none, to_int], self.pre_compaction_messages_length) if self.pre_compaction_tokens is not None: - result["preCompactionTokens"] = from_union([from_none, to_float], self.pre_compaction_tokens) + result["preCompactionTokens"] = from_union([from_none, to_int], self.pre_compaction_tokens) if self.request_id is not None: result["requestId"] = from_union([from_none, from_str], self.request_id) if self.summary_content is not None: result["summaryContent"] = from_union([from_none, from_str], self.summary_content) if self.system_tokens is not None: - result["systemTokens"] = from_union([from_none, to_float], self.system_tokens) + result["systemTokens"] = from_union([from_none, to_int], self.system_tokens) if self.tokens_removed is not None: - result["tokensRemoved"] = from_union([from_none, to_float], self.tokens_removed) + result["tokensRemoved"] = from_union([from_none, to_int], self.tokens_removed) if self.tool_definitions_tokens is not None: - result["toolDefinitionsTokens"] = from_union([from_none, to_float], self.tool_definitions_tokens) + result["toolDefinitionsTokens"] = from_union([from_none, to_int], self.tool_definitions_tokens) return result @dataclass class SessionCompactionStartData: "Context window breakdown at the start of LLM-powered conversation compaction" - conversation_tokens: float | None = None - system_tokens: float | None = None - tool_definitions_tokens: float | None = None + conversation_tokens: int | None = None + system_tokens: int | None = None + tool_definitions_tokens: int | None = None @staticmethod def from_dict(obj: Any) -> "SessionCompactionStartData": assert isinstance(obj, dict) - conversation_tokens = from_union([from_none, from_float], obj.get("conversationTokens")) - system_tokens = from_union([from_none, from_float], obj.get("systemTokens")) - tool_definitions_tokens = from_union([from_none, from_float], obj.get("toolDefinitionsTokens")) + conversation_tokens = from_union([from_none, from_int], obj.get("conversationTokens")) + system_tokens = from_union([from_none, from_int], obj.get("systemTokens")) + tool_definitions_tokens = from_union([from_none, from_int], obj.get("toolDefinitionsTokens")) return SessionCompactionStartData( conversation_tokens=conversation_tokens, system_tokens=system_tokens, @@ -2509,11 +2509,11 @@ def from_dict(obj: Any) -> "SessionCompactionStartData": def to_dict(self) -> dict: result: dict = {} if self.conversation_tokens is not None: - result["conversationTokens"] = from_union([from_none, to_float], self.conversation_tokens) + result["conversationTokens"] = from_union([from_none, to_int], self.conversation_tokens) if self.system_tokens is not None: - result["systemTokens"] = from_union([from_none, to_float], self.system_tokens) + result["systemTokens"] = from_union([from_none, to_int], self.system_tokens) if self.tool_definitions_tokens is not None: - result["toolDefinitionsTokens"] = from_union([from_none, to_float], self.tool_definitions_tokens) + result["toolDefinitionsTokens"] = from_union([from_none, to_int], self.tool_definitions_tokens) return result @@ -2963,7 +2963,7 @@ def to_dict(self) -> dict: @dataclass class SessionResumeData: "Session resume metadata including current context and event count" - event_count: float + event_count: int resume_time: datetime already_in_use: bool | None = None context: WorkingDirectoryContext | None = None @@ -2977,7 +2977,7 @@ class SessionResumeData: @staticmethod def from_dict(obj: Any) -> "SessionResumeData": assert isinstance(obj, dict) - event_count = from_float(obj.get("eventCount")) + event_count = from_int(obj.get("eventCount")) resume_time = from_datetime(obj.get("resumeTime")) already_in_use = from_union([from_none, from_bool], obj.get("alreadyInUse")) context = from_union([from_none, WorkingDirectoryContext.from_dict], obj.get("context")) @@ -3002,7 +3002,7 @@ def from_dict(obj: Any) -> "SessionResumeData": def to_dict(self) -> dict: result: dict = {} - result["eventCount"] = to_float(self.event_count) + result["eventCount"] = to_int(self.event_count) result["resumeTime"] = to_datetime(self.resume_time) if self.already_in_use is not None: result["alreadyInUse"] = from_union([from_none, from_bool], self.already_in_use) @@ -3084,36 +3084,36 @@ class SessionShutdownData: "Session termination metrics including usage statistics, code changes, and shutdown reason" code_changes: ShutdownCodeChanges model_metrics: dict[str, ShutdownModelMetric] - session_start_time: float + session_start_time: int shutdown_type: ShutdownType total_api_duration: timedelta - total_premium_requests: float - conversation_tokens: float | None = None + total_premium_requests: int + conversation_tokens: int | None = None current_model: str | None = None - current_tokens: float | None = None + current_tokens: int | None = None error_reason: str | None = None - system_tokens: float | None = None + system_tokens: int | None = None token_details: dict[str, ShutdownTokenDetail] | None = None - tool_definitions_tokens: float | None = None - total_nano_aiu: float | None = None + tool_definitions_tokens: int | None = None + total_nano_aiu: int | None = None @staticmethod def from_dict(obj: Any) -> "SessionShutdownData": assert isinstance(obj, dict) code_changes = ShutdownCodeChanges.from_dict(obj.get("codeChanges")) model_metrics = from_dict(ShutdownModelMetric.from_dict, obj.get("modelMetrics")) - session_start_time = from_float(obj.get("sessionStartTime")) + session_start_time = from_int(obj.get("sessionStartTime")) shutdown_type = parse_enum(ShutdownType, obj.get("shutdownType")) total_api_duration = from_timedelta(obj.get("totalApiDurationMs")) - total_premium_requests = from_float(obj.get("totalPremiumRequests")) - conversation_tokens = from_union([from_none, from_float], obj.get("conversationTokens")) + total_premium_requests = from_int(obj.get("totalPremiumRequests")) + conversation_tokens = from_union([from_none, from_int], obj.get("conversationTokens")) current_model = from_union([from_none, from_str], obj.get("currentModel")) - current_tokens = from_union([from_none, from_float], obj.get("currentTokens")) + current_tokens = from_union([from_none, from_int], obj.get("currentTokens")) error_reason = from_union([from_none, from_str], obj.get("errorReason")) - system_tokens = from_union([from_none, from_float], obj.get("systemTokens")) + system_tokens = from_union([from_none, from_int], obj.get("systemTokens")) token_details = from_union([from_none, lambda x: from_dict(ShutdownTokenDetail.from_dict, x)], obj.get("tokenDetails")) - tool_definitions_tokens = from_union([from_none, from_float], obj.get("toolDefinitionsTokens")) - total_nano_aiu = from_union([from_none, from_float], obj.get("totalNanoAiu")) + tool_definitions_tokens = from_union([from_none, from_int], obj.get("toolDefinitionsTokens")) + total_nano_aiu = from_union([from_none, from_int], obj.get("totalNanoAiu")) return SessionShutdownData( code_changes=code_changes, model_metrics=model_metrics, @@ -3135,26 +3135,26 @@ def to_dict(self) -> dict: result: dict = {} result["codeChanges"] = to_class(ShutdownCodeChanges, self.code_changes) result["modelMetrics"] = from_dict(lambda x: to_class(ShutdownModelMetric, x), self.model_metrics) - result["sessionStartTime"] = to_float(self.session_start_time) + result["sessionStartTime"] = to_int(self.session_start_time) result["shutdownType"] = to_enum(ShutdownType, self.shutdown_type) - result["totalApiDurationMs"] = to_timedelta(self.total_api_duration) - result["totalPremiumRequests"] = to_float(self.total_premium_requests) + result["totalApiDurationMs"] = to_timedelta_int(self.total_api_duration) + result["totalPremiumRequests"] = to_int(self.total_premium_requests) if self.conversation_tokens is not None: - result["conversationTokens"] = from_union([from_none, to_float], self.conversation_tokens) + result["conversationTokens"] = from_union([from_none, to_int], self.conversation_tokens) if self.current_model is not None: result["currentModel"] = from_union([from_none, from_str], self.current_model) if self.current_tokens is not None: - result["currentTokens"] = from_union([from_none, to_float], self.current_tokens) + result["currentTokens"] = from_union([from_none, to_int], self.current_tokens) if self.error_reason is not None: result["errorReason"] = from_union([from_none, from_str], self.error_reason) if self.system_tokens is not None: - result["systemTokens"] = from_union([from_none, to_float], self.system_tokens) + result["systemTokens"] = from_union([from_none, to_int], self.system_tokens) if self.token_details is not None: result["tokenDetails"] = from_union([from_none, lambda x: from_dict(lambda x: to_class(ShutdownTokenDetail, x), x)], self.token_details) if self.tool_definitions_tokens is not None: - result["toolDefinitionsTokens"] = from_union([from_none, to_float], self.tool_definitions_tokens) + result["toolDefinitionsTokens"] = from_union([from_none, to_int], self.tool_definitions_tokens) if self.total_nano_aiu is not None: - result["totalNanoAiu"] = from_union([from_none, to_float], self.total_nano_aiu) + result["totalNanoAiu"] = from_union([from_none, to_int], self.total_nano_aiu) return result @@ -3180,13 +3180,13 @@ def to_dict(self) -> dict: @dataclass class SessionSnapshotRewindData: "Session rewind details including target event and count of removed events" - events_removed: float + events_removed: int up_to_event_id: str @staticmethod def from_dict(obj: Any) -> "SessionSnapshotRewindData": assert isinstance(obj, dict) - events_removed = from_float(obj.get("eventsRemoved")) + events_removed = from_int(obj.get("eventsRemoved")) up_to_event_id = from_str(obj.get("upToEventId")) return SessionSnapshotRewindData( events_removed=events_removed, @@ -3195,7 +3195,7 @@ def from_dict(obj: Any) -> "SessionSnapshotRewindData": def to_dict(self) -> dict: result: dict = {} - result["eventsRemoved"] = to_float(self.events_removed) + result["eventsRemoved"] = to_int(self.events_removed) result["upToEventId"] = from_str(self.up_to_event_id) return result @@ -3207,7 +3207,7 @@ class SessionStartData: producer: str session_id: str start_time: datetime - version: float + version: int already_in_use: bool | None = None context: WorkingDirectoryContext | None = None detached_from_spawning_parent_session_id: str | None = None @@ -3223,7 +3223,7 @@ def from_dict(obj: Any) -> "SessionStartData": producer = from_str(obj.get("producer")) session_id = from_str(obj.get("sessionId")) start_time = from_datetime(obj.get("startTime")) - version = from_float(obj.get("version")) + version = from_int(obj.get("version")) already_in_use = from_union([from_none, from_bool], obj.get("alreadyInUse")) context = from_union([from_none, WorkingDirectoryContext.from_dict], obj.get("context")) detached_from_spawning_parent_session_id = from_union([from_none, from_str], obj.get("detachedFromSpawningParentSessionId")) @@ -3252,7 +3252,7 @@ def to_dict(self) -> dict: result["producer"] = from_str(self.producer) result["sessionId"] = from_str(self.session_id) result["startTime"] = to_datetime(self.start_time) - result["version"] = to_float(self.version) + result["version"] = to_int(self.version) if self.already_in_use is not None: result["alreadyInUse"] = from_union([from_none, from_bool], self.already_in_use) if self.context is not None: @@ -3336,26 +3336,26 @@ def to_dict(self) -> dict: @dataclass class SessionTruncationData: "Conversation truncation statistics including token counts and removed content metrics" - messages_removed_during_truncation: float + messages_removed_during_truncation: int performed_by: str - post_truncation_messages_length: float - post_truncation_tokens_in_messages: float - pre_truncation_messages_length: float - pre_truncation_tokens_in_messages: float - token_limit: float - tokens_removed_during_truncation: float + post_truncation_messages_length: int + post_truncation_tokens_in_messages: int + pre_truncation_messages_length: int + pre_truncation_tokens_in_messages: int + token_limit: int + tokens_removed_during_truncation: int @staticmethod def from_dict(obj: Any) -> "SessionTruncationData": assert isinstance(obj, dict) - messages_removed_during_truncation = from_float(obj.get("messagesRemovedDuringTruncation")) + messages_removed_during_truncation = from_int(obj.get("messagesRemovedDuringTruncation")) performed_by = from_str(obj.get("performedBy")) - post_truncation_messages_length = from_float(obj.get("postTruncationMessagesLength")) - post_truncation_tokens_in_messages = from_float(obj.get("postTruncationTokensInMessages")) - pre_truncation_messages_length = from_float(obj.get("preTruncationMessagesLength")) - pre_truncation_tokens_in_messages = from_float(obj.get("preTruncationTokensInMessages")) - token_limit = from_float(obj.get("tokenLimit")) - tokens_removed_during_truncation = from_float(obj.get("tokensRemovedDuringTruncation")) + post_truncation_messages_length = from_int(obj.get("postTruncationMessagesLength")) + post_truncation_tokens_in_messages = from_int(obj.get("postTruncationTokensInMessages")) + pre_truncation_messages_length = from_int(obj.get("preTruncationMessagesLength")) + pre_truncation_tokens_in_messages = from_int(obj.get("preTruncationTokensInMessages")) + token_limit = from_int(obj.get("tokenLimit")) + tokens_removed_during_truncation = from_int(obj.get("tokensRemovedDuringTruncation")) return SessionTruncationData( messages_removed_during_truncation=messages_removed_during_truncation, performed_by=performed_by, @@ -3369,38 +3369,38 @@ def from_dict(obj: Any) -> "SessionTruncationData": def to_dict(self) -> dict: result: dict = {} - result["messagesRemovedDuringTruncation"] = to_float(self.messages_removed_during_truncation) + result["messagesRemovedDuringTruncation"] = to_int(self.messages_removed_during_truncation) result["performedBy"] = from_str(self.performed_by) - result["postTruncationMessagesLength"] = to_float(self.post_truncation_messages_length) - result["postTruncationTokensInMessages"] = to_float(self.post_truncation_tokens_in_messages) - result["preTruncationMessagesLength"] = to_float(self.pre_truncation_messages_length) - result["preTruncationTokensInMessages"] = to_float(self.pre_truncation_tokens_in_messages) - result["tokenLimit"] = to_float(self.token_limit) - result["tokensRemovedDuringTruncation"] = to_float(self.tokens_removed_during_truncation) + result["postTruncationMessagesLength"] = to_int(self.post_truncation_messages_length) + result["postTruncationTokensInMessages"] = to_int(self.post_truncation_tokens_in_messages) + result["preTruncationMessagesLength"] = to_int(self.pre_truncation_messages_length) + result["preTruncationTokensInMessages"] = to_int(self.pre_truncation_tokens_in_messages) + result["tokenLimit"] = to_int(self.token_limit) + result["tokensRemovedDuringTruncation"] = to_int(self.tokens_removed_during_truncation) return result @dataclass class SessionUsageInfoData: "Current context window usage statistics including token and message counts" - current_tokens: float - messages_length: float - token_limit: float - conversation_tokens: float | None = None + current_tokens: int + messages_length: int + token_limit: int + conversation_tokens: int | None = None is_initial: bool | None = None - system_tokens: float | None = None - tool_definitions_tokens: float | None = None + system_tokens: int | None = None + tool_definitions_tokens: int | None = None @staticmethod def from_dict(obj: Any) -> "SessionUsageInfoData": 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_none, from_float], obj.get("conversationTokens")) + current_tokens = from_int(obj.get("currentTokens")) + messages_length = from_int(obj.get("messagesLength")) + token_limit = from_int(obj.get("tokenLimit")) + conversation_tokens = from_union([from_none, from_int], obj.get("conversationTokens")) is_initial = from_union([from_none, from_bool], obj.get("isInitial")) - system_tokens = from_union([from_none, from_float], obj.get("systemTokens")) - tool_definitions_tokens = from_union([from_none, from_float], obj.get("toolDefinitionsTokens")) + system_tokens = from_union([from_none, from_int], obj.get("systemTokens")) + tool_definitions_tokens = from_union([from_none, from_int], obj.get("toolDefinitionsTokens")) return SessionUsageInfoData( current_tokens=current_tokens, messages_length=messages_length, @@ -3413,17 +3413,17 @@ def from_dict(obj: Any) -> "SessionUsageInfoData": def to_dict(self) -> dict: result: dict = {} - result["currentTokens"] = to_float(self.current_tokens) - result["messagesLength"] = to_float(self.messages_length) - result["tokenLimit"] = to_float(self.token_limit) + result["currentTokens"] = to_int(self.current_tokens) + result["messagesLength"] = to_int(self.messages_length) + result["tokenLimit"] = to_int(self.token_limit) if self.conversation_tokens is not None: - result["conversationTokens"] = from_union([from_none, to_float], self.conversation_tokens) + result["conversationTokens"] = from_union([from_none, to_int], self.conversation_tokens) if self.is_initial is not None: result["isInitial"] = from_union([from_none, from_bool], self.is_initial) if self.system_tokens is not None: - result["systemTokens"] = from_union([from_none, to_float], self.system_tokens) + result["systemTokens"] = from_union([from_none, to_int], self.system_tokens) if self.tool_definitions_tokens is not None: - result["toolDefinitionsTokens"] = from_union([from_none, to_float], self.tool_definitions_tokens) + result["toolDefinitionsTokens"] = from_union([from_none, to_int], self.tool_definitions_tokens) return result @@ -3482,15 +3482,15 @@ def to_dict(self) -> dict: class ShutdownCodeChanges: "Aggregate code change metrics for the session" files_modified: list[str] - lines_added: float - lines_removed: float + lines_added: int + lines_removed: int @staticmethod 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")) + lines_added = from_int(obj.get("linesAdded")) + lines_removed = from_int(obj.get("linesRemoved")) return ShutdownCodeChanges( files_modified=files_modified, lines_added=lines_added, @@ -3500,8 +3500,8 @@ def from_dict(obj: Any) -> "ShutdownCodeChanges": def to_dict(self) -> dict: result: dict = {} result["filesModified"] = from_list(from_str, self.files_modified) - result["linesAdded"] = to_float(self.lines_added) - result["linesRemoved"] = to_float(self.lines_removed) + result["linesAdded"] = to_int(self.lines_added) + result["linesRemoved"] = to_int(self.lines_removed) return result @@ -3511,7 +3511,7 @@ class ShutdownModelMetric: requests: ShutdownModelMetricRequests usage: ShutdownModelMetricUsage token_details: dict[str, ShutdownModelMetricTokenDetail] | None = None - total_nano_aiu: float | None = None + total_nano_aiu: int | None = None @staticmethod def from_dict(obj: Any) -> "ShutdownModelMetric": @@ -3519,7 +3519,7 @@ def from_dict(obj: Any) -> "ShutdownModelMetric": requests = ShutdownModelMetricRequests.from_dict(obj.get("requests")) usage = ShutdownModelMetricUsage.from_dict(obj.get("usage")) token_details = from_union([from_none, lambda x: from_dict(ShutdownModelMetricTokenDetail.from_dict, x)], obj.get("tokenDetails")) - total_nano_aiu = from_union([from_none, from_float], obj.get("totalNanoAiu")) + total_nano_aiu = from_union([from_none, from_int], obj.get("totalNanoAiu")) return ShutdownModelMetric( requests=requests, usage=usage, @@ -3534,7 +3534,7 @@ def to_dict(self) -> dict: if self.token_details is not None: result["tokenDetails"] = from_union([from_none, lambda x: from_dict(lambda x: to_class(ShutdownModelMetricTokenDetail, x), x)], self.token_details) if self.total_nano_aiu is not None: - result["totalNanoAiu"] = from_union([from_none, to_float], self.total_nano_aiu) + result["totalNanoAiu"] = from_union([from_none, to_int], self.total_nano_aiu) return result @@ -3542,13 +3542,13 @@ def to_dict(self) -> dict: class ShutdownModelMetricRequests: "Request count and cost metrics" cost: float - count: float + count: int @staticmethod def from_dict(obj: Any) -> "ShutdownModelMetricRequests": assert isinstance(obj, dict) cost = from_float(obj.get("cost")) - count = from_float(obj.get("count")) + count = from_int(obj.get("count")) return ShutdownModelMetricRequests( cost=cost, count=count, @@ -3557,46 +3557,46 @@ def from_dict(obj: Any) -> "ShutdownModelMetricRequests": def to_dict(self) -> dict: result: dict = {} result["cost"] = to_float(self.cost) - result["count"] = to_float(self.count) + result["count"] = to_int(self.count) return result @dataclass class ShutdownModelMetricTokenDetail: "Schema for the `ShutdownModelMetricTokenDetail` type." - token_count: float + token_count: int @staticmethod def from_dict(obj: Any) -> "ShutdownModelMetricTokenDetail": assert isinstance(obj, dict) - token_count = from_float(obj.get("tokenCount")) + token_count = from_int(obj.get("tokenCount")) return ShutdownModelMetricTokenDetail( token_count=token_count, ) def to_dict(self) -> dict: result: dict = {} - result["tokenCount"] = to_float(self.token_count) + result["tokenCount"] = to_int(self.token_count) return result @dataclass class ShutdownModelMetricUsage: "Token usage breakdown" - cache_read_tokens: float - cache_write_tokens: float - input_tokens: float - output_tokens: float - reasoning_tokens: float | None = None + cache_read_tokens: int + cache_write_tokens: int + input_tokens: int + output_tokens: int + reasoning_tokens: int | None = None @staticmethod 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")) - reasoning_tokens = from_union([from_none, from_float], obj.get("reasoningTokens")) + 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_none, from_int], obj.get("reasoningTokens")) return ShutdownModelMetricUsage( cache_read_tokens=cache_read_tokens, cache_write_tokens=cache_write_tokens, @@ -3607,31 +3607,31 @@ def from_dict(obj: Any) -> "ShutdownModelMetricUsage": def to_dict(self) -> dict: result: dict = {} - result["cacheReadTokens"] = to_float(self.cache_read_tokens) - result["cacheWriteTokens"] = to_float(self.cache_write_tokens) - result["inputTokens"] = to_float(self.input_tokens) - result["outputTokens"] = to_float(self.output_tokens) + result["cacheReadTokens"] = to_int(self.cache_read_tokens) + result["cacheWriteTokens"] = to_int(self.cache_write_tokens) + result["inputTokens"] = to_int(self.input_tokens) + result["outputTokens"] = to_int(self.output_tokens) if self.reasoning_tokens is not None: - result["reasoningTokens"] = from_union([from_none, to_float], self.reasoning_tokens) + result["reasoningTokens"] = from_union([from_none, to_int], self.reasoning_tokens) return result @dataclass class ShutdownTokenDetail: "Schema for the `ShutdownTokenDetail` type." - token_count: float + token_count: int @staticmethod def from_dict(obj: Any) -> "ShutdownTokenDetail": assert isinstance(obj, dict) - token_count = from_float(obj.get("tokenCount")) + token_count = from_int(obj.get("tokenCount")) return ShutdownTokenDetail( token_count=token_count, ) def to_dict(self) -> dict: result: dict = {} - result["tokenCount"] = to_float(self.token_count) + result["tokenCount"] = to_int(self.token_count) return result @@ -3730,8 +3730,8 @@ class SubagentCompletedData: tool_call_id: str duration: timedelta | None = None model: str | None = None - total_tokens: float | None = None - total_tool_calls: float | None = None + total_tokens: int | None = None + total_tool_calls: int | None = None @staticmethod def from_dict(obj: Any) -> "SubagentCompletedData": @@ -3741,8 +3741,8 @@ def from_dict(obj: Any) -> "SubagentCompletedData": tool_call_id = from_str(obj.get("toolCallId")) duration = from_union([from_none, from_timedelta], obj.get("durationMs")) model = from_union([from_none, from_str], obj.get("model")) - total_tokens = from_union([from_none, from_float], obj.get("totalTokens")) - total_tool_calls = from_union([from_none, from_float], obj.get("totalToolCalls")) + total_tokens = from_union([from_none, from_int], obj.get("totalTokens")) + total_tool_calls = from_union([from_none, from_int], obj.get("totalToolCalls")) return SubagentCompletedData( agent_display_name=agent_display_name, agent_name=agent_name, @@ -3759,13 +3759,13 @@ def to_dict(self) -> dict: result["agentName"] = from_str(self.agent_name) result["toolCallId"] = from_str(self.tool_call_id) if self.duration is not None: - result["durationMs"] = from_union([from_none, to_timedelta], self.duration) + result["durationMs"] = from_union([from_none, to_timedelta_int], self.duration) if self.model is not None: result["model"] = from_union([from_none, from_str], self.model) if self.total_tokens is not None: - result["totalTokens"] = from_union([from_none, to_float], self.total_tokens) + result["totalTokens"] = from_union([from_none, to_int], self.total_tokens) if self.total_tool_calls is not None: - result["totalToolCalls"] = from_union([from_none, to_float], self.total_tool_calls) + result["totalToolCalls"] = from_union([from_none, to_int], self.total_tool_calls) return result @@ -3790,8 +3790,8 @@ class SubagentFailedData: tool_call_id: str duration: timedelta | None = None model: str | None = None - total_tokens: float | None = None - total_tool_calls: float | None = None + total_tokens: int | None = None + total_tool_calls: int | None = None @staticmethod def from_dict(obj: Any) -> "SubagentFailedData": @@ -3802,8 +3802,8 @@ def from_dict(obj: Any) -> "SubagentFailedData": tool_call_id = from_str(obj.get("toolCallId")) duration = from_union([from_none, from_timedelta], obj.get("durationMs")) model = from_union([from_none, from_str], obj.get("model")) - total_tokens = from_union([from_none, from_float], obj.get("totalTokens")) - total_tool_calls = from_union([from_none, from_float], obj.get("totalToolCalls")) + total_tokens = from_union([from_none, from_int], obj.get("totalTokens")) + total_tool_calls = from_union([from_none, from_int], obj.get("totalToolCalls")) return SubagentFailedData( agent_display_name=agent_display_name, agent_name=agent_name, @@ -3822,13 +3822,13 @@ def to_dict(self) -> dict: result["error"] = from_str(self.error) result["toolCallId"] = from_str(self.tool_call_id) if self.duration is not None: - result["durationMs"] = from_union([from_none, to_timedelta], self.duration) + result["durationMs"] = from_union([from_none, to_timedelta_int], self.duration) if self.model is not None: result["model"] = from_union([from_none, from_str], self.model) if self.total_tokens is not None: - result["totalTokens"] = from_union([from_none, to_float], self.total_tokens) + result["totalTokens"] = from_union([from_none, to_int], self.total_tokens) if self.total_tool_calls is not None: - result["totalToolCalls"] = from_union([from_none, to_float], self.total_tool_calls) + result["totalToolCalls"] = from_union([from_none, to_int], self.total_tool_calls) return result @@ -3961,7 +3961,7 @@ class SystemNotification: agent_type: str | None = None description: str | None = None entry_id: str | None = None - exit_code: float | None = None + exit_code: int | None = None prompt: str | None = None sender_name: str | None = None sender_type: str | None = None @@ -3980,7 +3980,7 @@ def from_dict(obj: Any) -> "SystemNotification": agent_type = from_union([from_none, from_str], obj.get("agentType")) description = from_union([from_none, from_str], obj.get("description")) entry_id = from_union([from_none, from_str], obj.get("entryId")) - exit_code = from_union([from_none, from_float], obj.get("exitCode")) + exit_code = from_union([from_none, from_int], obj.get("exitCode")) prompt = from_union([from_none, from_str], obj.get("prompt")) sender_name = from_union([from_none, from_str], obj.get("senderName")) sender_type = from_union([from_none, from_str], obj.get("senderType")) @@ -4020,7 +4020,7 @@ def to_dict(self) -> dict: if self.entry_id is not None: result["entryId"] = from_union([from_none, from_str], self.entry_id) if self.exit_code is not None: - result["exitCode"] = from_union([from_none, to_float], self.exit_code) + result["exitCode"] = from_union([from_none, to_int], self.exit_code) if self.prompt is not None: result["prompt"] = from_union([from_none, from_str], self.prompt) if self.sender_name is not None: @@ -4072,12 +4072,12 @@ class ToolExecutionCompleteContent: cwd: str | None = None data: str | None = None description: str | None = None - exit_code: float | None = None + exit_code: int | None = None icons: list[ToolExecutionCompleteContentResourceLinkIcon] | None = None mime_type: str | None = None name: str | None = None resource: ToolExecutionCompleteContentResourceDetails | None = None - size: float | None = None + size: int | None = None text: str | None = None title: str | None = None uri: str | None = None @@ -4089,12 +4089,12 @@ def from_dict(obj: Any) -> "ToolExecutionCompleteContent": cwd = from_union([from_none, from_str], obj.get("cwd")) data = from_union([from_none, from_str], obj.get("data")) description = from_union([from_none, from_str], obj.get("description")) - exit_code = from_union([from_none, from_float], obj.get("exitCode")) + exit_code = from_union([from_none, from_int], obj.get("exitCode")) icons = from_union([from_none, lambda x: from_list(ToolExecutionCompleteContentResourceLinkIcon.from_dict, x)], obj.get("icons")) mime_type = from_union([from_none, from_str], obj.get("mimeType")) name = from_union([from_none, from_str], obj.get("name")) resource = from_union([from_none, lambda x: from_union([EmbeddedTextResourceContents.from_dict, EmbeddedBlobResourceContents.from_dict], x)], obj.get("resource")) - size = from_union([from_none, from_float], obj.get("size")) + size = from_union([from_none, from_int], obj.get("size")) text = from_union([from_none, from_str], obj.get("text")) title = from_union([from_none, from_str], obj.get("title")) uri = from_union([from_none, from_str], obj.get("uri")) @@ -4124,7 +4124,7 @@ def to_dict(self) -> dict: if self.description is not None: result["description"] = from_union([from_none, from_str], self.description) if self.exit_code is not None: - result["exitCode"] = from_union([from_none, to_float], self.exit_code) + result["exitCode"] = from_union([from_none, to_int], self.exit_code) if self.icons is not None: result["icons"] = from_union([from_none, lambda x: from_list(lambda x: to_class(ToolExecutionCompleteContentResourceLinkIcon, x), x)], self.icons) if self.mime_type is not None: @@ -4134,7 +4134,7 @@ def to_dict(self) -> dict: if self.resource is not None: result["resource"] = from_union([from_none, lambda x: from_union([lambda x: to_class(EmbeddedTextResourceContents, x), lambda x: to_class(EmbeddedBlobResourceContents, x)], x)], self.resource) if self.size is not None: - result["size"] = from_union([from_none, to_float], self.size) + result["size"] = from_union([from_none, to_int], self.size) if self.text is not None: result["text"] = from_union([from_none, from_str], self.text) if self.title is not None: @@ -4494,7 +4494,7 @@ class UserMessageAttachment: file_path: str | None = None line_range: UserMessageAttachmentFileLineRange | None = None mime_type: str | None = None - number: float | None = None + number: int | None = None path: str | None = None reference_type: UserMessageAttachmentGithubReferenceType | None = None selection: UserMessageAttachmentSelectionDetails | None = None @@ -4512,7 +4512,7 @@ def from_dict(obj: Any) -> "UserMessageAttachment": file_path = from_union([from_none, from_str], obj.get("filePath")) line_range = from_union([from_none, UserMessageAttachmentFileLineRange.from_dict], obj.get("lineRange")) mime_type = from_union([from_none, from_str], obj.get("mimeType")) - number = from_union([from_none, from_float], obj.get("number")) + number = from_union([from_none, from_int], obj.get("number")) path = from_union([from_none, from_str], obj.get("path")) reference_type = from_union([from_none, lambda x: parse_enum(UserMessageAttachmentGithubReferenceType, x)], obj.get("referenceType")) selection = from_union([from_none, UserMessageAttachmentSelectionDetails.from_dict], obj.get("selection")) @@ -4551,7 +4551,7 @@ def to_dict(self) -> dict: if self.mime_type is not None: result["mimeType"] = from_union([from_none, from_str], self.mime_type) if self.number is not None: - result["number"] = from_union([from_none, to_float], self.number) + result["number"] = from_union([from_none, to_int], self.number) if self.path is not None: result["path"] = from_union([from_none, from_str], self.path) if self.reference_type is not None: @@ -4572,14 +4572,14 @@ def to_dict(self) -> dict: @dataclass class UserMessageAttachmentFileLineRange: "Optional line range to scope the attachment to a specific section of the file" - end: float - start: float + end: int + start: int @staticmethod def from_dict(obj: Any) -> "UserMessageAttachmentFileLineRange": assert isinstance(obj, dict) - end = from_float(obj.get("end")) - start = from_float(obj.get("start")) + end = from_int(obj.get("end")) + start = from_int(obj.get("start")) return UserMessageAttachmentFileLineRange( end=end, start=start, @@ -4587,8 +4587,8 @@ def from_dict(obj: Any) -> "UserMessageAttachmentFileLineRange": def to_dict(self) -> dict: result: dict = {} - result["end"] = to_float(self.end) - result["start"] = to_float(self.start) + result["end"] = to_int(self.end) + result["start"] = to_int(self.start) return result @@ -4618,14 +4618,14 @@ def to_dict(self) -> dict: @dataclass class UserMessageAttachmentSelectionDetailsEnd: "End position of the selection" - character: float - line: float + character: int + line: int @staticmethod def from_dict(obj: Any) -> "UserMessageAttachmentSelectionDetailsEnd": assert isinstance(obj, dict) - character = from_float(obj.get("character")) - line = from_float(obj.get("line")) + character = from_int(obj.get("character")) + line = from_int(obj.get("line")) return UserMessageAttachmentSelectionDetailsEnd( character=character, line=line, @@ -4633,22 +4633,22 @@ def from_dict(obj: Any) -> "UserMessageAttachmentSelectionDetailsEnd": def to_dict(self) -> dict: result: dict = {} - result["character"] = to_float(self.character) - result["line"] = to_float(self.line) + result["character"] = to_int(self.character) + result["line"] = to_int(self.line) return result @dataclass class UserMessageAttachmentSelectionDetailsStart: "Start position of the selection" - character: float - line: float + character: int + line: int @staticmethod def from_dict(obj: Any) -> "UserMessageAttachmentSelectionDetailsStart": assert isinstance(obj, dict) - character = from_float(obj.get("character")) - line = from_float(obj.get("line")) + character = from_int(obj.get("character")) + line = from_int(obj.get("line")) return UserMessageAttachmentSelectionDetailsStart( character=character, line=line, @@ -4656,8 +4656,8 @@ def from_dict(obj: Any) -> "UserMessageAttachmentSelectionDetailsStart": def to_dict(self) -> dict: result: dict = {} - result["character"] = to_float(self.character) - result["line"] = to_float(self.line) + result["character"] = to_int(self.character) + result["line"] = to_int(self.line) return result diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs index 6f7e97ad7..7596405bd 100644 --- a/rust/src/generated/api_types.rs +++ b/rust/src/generated/api_types.rs @@ -7,9 +7,10 @@ use std::collections::HashMap; use serde::{Deserialize, Serialize}; use super::session_events::{ - McpServerSource, McpServerStatus, ReasoningSummary, SessionMode, SkillSource, + AbortReason, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, + ReasoningSummary, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval, }; -use crate::types::{RequestId, SessionId}; +use crate::types::{RequestId, SessionEvent, SessionId}; /// JSON-RPC method name constants. pub mod rpc_methods { @@ -47,14 +48,58 @@ pub mod rpc_methods { pub const SESSIONS_FORK: &str = "sessions.fork"; /// `sessions.connect` pub const SESSIONS_CONNECT: &str = "sessions.connect"; + /// `sessions.list` + pub const SESSIONS_LIST: &str = "sessions.list"; + /// `sessions.findByTaskId` + pub const SESSIONS_FINDBYTASKID: &str = "sessions.findByTaskId"; + /// `sessions.findByPrefix` + pub const SESSIONS_FINDBYPREFIX: &str = "sessions.findByPrefix"; + /// `sessions.getLastForContext` + pub const SESSIONS_GETLASTFORCONTEXT: &str = "sessions.getLastForContext"; + /// `sessions.getEventFilePath` + pub const SESSIONS_GETEVENTFILEPATH: &str = "sessions.getEventFilePath"; + /// `sessions.getSizes` + pub const SESSIONS_GETSIZES: &str = "sessions.getSizes"; + /// `sessions.checkInUse` + pub const SESSIONS_CHECKINUSE: &str = "sessions.checkInUse"; + /// `sessions.getPersistedRemoteSteerable` + pub const SESSIONS_GETPERSISTEDREMOTESTEERABLE: &str = "sessions.getPersistedRemoteSteerable"; + /// `sessions.close` + pub const SESSIONS_CLOSE: &str = "sessions.close"; + /// `sessions.bulkDelete` + pub const SESSIONS_BULKDELETE: &str = "sessions.bulkDelete"; + /// `sessions.pruneOld` + pub const SESSIONS_PRUNEOLD: &str = "sessions.pruneOld"; + /// `sessions.save` + pub const SESSIONS_SAVE: &str = "sessions.save"; + /// `sessions.releaseLock` + pub const SESSIONS_RELEASELOCK: &str = "sessions.releaseLock"; + /// `sessions.enrichMetadata` + pub const SESSIONS_ENRICHMETADATA: &str = "sessions.enrichMetadata"; + /// `sessions.reloadPluginHooks` + pub const SESSIONS_RELOADPLUGINHOOKS: &str = "sessions.reloadPluginHooks"; + /// `sessions.loadDeferredRepoHooks` + pub const SESSIONS_LOADDEFERREDREPOHOOKS: &str = "sessions.loadDeferredRepoHooks"; + /// `sessions.setAdditionalPlugins` + pub const SESSIONS_SETADDITIONALPLUGINS: &str = "sessions.setAdditionalPlugins"; /// `session.suspend` pub const SESSION_SUSPEND: &str = "session.suspend"; + /// `session.send` + pub const SESSION_SEND: &str = "session.send"; + /// `session.abort` + pub const SESSION_ABORT: &str = "session.abort"; + /// `session.shutdown` + pub const SESSION_SHUTDOWN: &str = "session.shutdown"; /// `session.auth.getStatus` pub const SESSION_AUTH_GETSTATUS: &str = "session.auth.getStatus"; + /// `session.auth.setCredentials` + pub const SESSION_AUTH_SETCREDENTIALS: &str = "session.auth.setCredentials"; /// `session.model.getCurrent` pub const SESSION_MODEL_GETCURRENT: &str = "session.model.getCurrent"; /// `session.model.switchTo` pub const SESSION_MODEL_SWITCHTO: &str = "session.model.switchTo"; + /// `session.model.setReasoningEffort` + pub const SESSION_MODEL_SETREASONINGEFFORT: &str = "session.model.setReasoningEffort"; /// `session.mode.get` pub const SESSION_MODE_GET: &str = "session.mode.get"; /// `session.mode.set` @@ -63,6 +108,8 @@ pub mod rpc_methods { pub const SESSION_NAME_GET: &str = "session.name.get"; /// `session.name.set` pub const SESSION_NAME_SET: &str = "session.name.set"; + /// `session.name.setAuto` + pub const SESSION_NAME_SETAUTO: &str = "session.name.setAuto"; /// `session.plan.read` pub const SESSION_PLAN_READ: &str = "session.plan.read"; /// `session.plan.update` @@ -77,6 +124,12 @@ pub mod rpc_methods { pub const SESSION_WORKSPACES_READFILE: &str = "session.workspaces.readFile"; /// `session.workspaces.createFile` pub const SESSION_WORKSPACES_CREATEFILE: &str = "session.workspaces.createFile"; + /// `session.workspaces.listCheckpoints` + pub const SESSION_WORKSPACES_LISTCHECKPOINTS: &str = "session.workspaces.listCheckpoints"; + /// `session.workspaces.readCheckpoint` + pub const SESSION_WORKSPACES_READCHECKPOINT: &str = "session.workspaces.readCheckpoint"; + /// `session.workspaces.saveLargePaste` + pub const SESSION_WORKSPACES_SAVELARGEPASTE: &str = "session.workspaces.saveLargePaste"; /// `session.instructions.getSources` pub const SESSION_INSTRUCTIONS_GETSOURCES: &str = "session.instructions.getSources"; /// `session.fleet.start` @@ -95,8 +148,19 @@ pub mod rpc_methods { pub const SESSION_TASKS_STARTAGENT: &str = "session.tasks.startAgent"; /// `session.tasks.list` pub const SESSION_TASKS_LIST: &str = "session.tasks.list"; + /// `session.tasks.refresh` + pub const SESSION_TASKS_REFRESH: &str = "session.tasks.refresh"; + /// `session.tasks.waitForPending` + pub const SESSION_TASKS_WAITFORPENDING: &str = "session.tasks.waitForPending"; + /// `session.tasks.getProgress` + pub const SESSION_TASKS_GETPROGRESS: &str = "session.tasks.getProgress"; + /// `session.tasks.getCurrentPromotable` + pub const SESSION_TASKS_GETCURRENTPROMOTABLE: &str = "session.tasks.getCurrentPromotable"; /// `session.tasks.promoteToBackground` pub const SESSION_TASKS_PROMOTETOBACKGROUND: &str = "session.tasks.promoteToBackground"; + /// `session.tasks.promoteCurrentToBackground` + pub const SESSION_TASKS_PROMOTECURRENTTOBACKGROUND: &str = + "session.tasks.promoteCurrentToBackground"; /// `session.tasks.cancel` pub const SESSION_TASKS_CANCEL: &str = "session.tasks.cancel"; /// `session.tasks.remove` @@ -105,12 +169,16 @@ pub mod rpc_methods { pub const SESSION_TASKS_SENDMESSAGE: &str = "session.tasks.sendMessage"; /// `session.skills.list` pub const SESSION_SKILLS_LIST: &str = "session.skills.list"; + /// `session.skills.getInvoked` + pub const SESSION_SKILLS_GETINVOKED: &str = "session.skills.getInvoked"; /// `session.skills.enable` pub const SESSION_SKILLS_ENABLE: &str = "session.skills.enable"; /// `session.skills.disable` pub const SESSION_SKILLS_DISABLE: &str = "session.skills.disable"; /// `session.skills.reload` pub const SESSION_SKILLS_RELOAD: &str = "session.skills.reload"; + /// `session.skills.ensureLoaded` + pub const SESSION_SKILLS_ENSURELOADED: &str = "session.skills.ensureLoaded"; /// `session.mcp.list` pub const SESSION_MCP_LIST: &str = "session.mcp.list"; /// `session.mcp.enable` @@ -119,10 +187,22 @@ pub mod rpc_methods { pub const SESSION_MCP_DISABLE: &str = "session.mcp.disable"; /// `session.mcp.reload` pub const SESSION_MCP_RELOAD: &str = "session.mcp.reload"; + /// `session.mcp.executeSampling` + pub const SESSION_MCP_EXECUTESAMPLING: &str = "session.mcp.executeSampling"; + /// `session.mcp.cancelSamplingExecution` + pub const SESSION_MCP_CANCELSAMPLINGEXECUTION: &str = "session.mcp.cancelSamplingExecution"; + /// `session.mcp.setEnvValueMode` + pub const SESSION_MCP_SETENVVALUEMODE: &str = "session.mcp.setEnvValueMode"; + /// `session.mcp.removeGitHub` + pub const SESSION_MCP_REMOVEGITHUB: &str = "session.mcp.removeGitHub"; /// `session.mcp.oauth.login` pub const SESSION_MCP_OAUTH_LOGIN: &str = "session.mcp.oauth.login"; /// `session.plugins.list` pub const SESSION_PLUGINS_LIST: &str = "session.plugins.list"; + /// `session.options.update` + pub const SESSION_OPTIONS_UPDATE: &str = "session.options.update"; + /// `session.lsp.initialize` + pub const SESSION_LSP_INITIALIZE: &str = "session.lsp.initialize"; /// `session.extensions.list` pub const SESSION_EXTENSIONS_LIST: &str = "session.extensions.list"; /// `session.extensions.enable` @@ -133,29 +213,91 @@ pub mod rpc_methods { pub const SESSION_EXTENSIONS_RELOAD: &str = "session.extensions.reload"; /// `session.tools.handlePendingToolCall` pub const SESSION_TOOLS_HANDLEPENDINGTOOLCALL: &str = "session.tools.handlePendingToolCall"; + /// `session.tools.initializeAndValidate` + pub const SESSION_TOOLS_INITIALIZEANDVALIDATE: &str = "session.tools.initializeAndValidate"; /// `session.commands.list` pub const SESSION_COMMANDS_LIST: &str = "session.commands.list"; /// `session.commands.invoke` pub const SESSION_COMMANDS_INVOKE: &str = "session.commands.invoke"; /// `session.commands.handlePendingCommand` pub const SESSION_COMMANDS_HANDLEPENDINGCOMMAND: &str = "session.commands.handlePendingCommand"; + /// `session.commands.execute` + pub const SESSION_COMMANDS_EXECUTE: &str = "session.commands.execute"; + /// `session.commands.enqueue` + pub const SESSION_COMMANDS_ENQUEUE: &str = "session.commands.enqueue"; /// `session.commands.respondToQueuedCommand` pub const SESSION_COMMANDS_RESPONDTOQUEUEDCOMMAND: &str = "session.commands.respondToQueuedCommand"; + /// `session.telemetry.setFeatureOverrides` + pub const SESSION_TELEMETRY_SETFEATUREOVERRIDES: &str = "session.telemetry.setFeatureOverrides"; /// `session.ui.elicitation` pub const SESSION_UI_ELICITATION: &str = "session.ui.elicitation"; /// `session.ui.handlePendingElicitation` pub const SESSION_UI_HANDLEPENDINGELICITATION: &str = "session.ui.handlePendingElicitation"; + /// `session.ui.handlePendingUserInput` + pub const SESSION_UI_HANDLEPENDINGUSERINPUT: &str = "session.ui.handlePendingUserInput"; + /// `session.ui.handlePendingSampling` + pub const SESSION_UI_HANDLEPENDINGSAMPLING: &str = "session.ui.handlePendingSampling"; + /// `session.ui.handlePendingAutoModeSwitch` + pub const SESSION_UI_HANDLEPENDINGAUTOMODESWITCH: &str = + "session.ui.handlePendingAutoModeSwitch"; + /// `session.ui.handlePendingExitPlanMode` + pub const SESSION_UI_HANDLEPENDINGEXITPLANMODE: &str = "session.ui.handlePendingExitPlanMode"; + /// `session.ui.registerDirectAutoModeSwitchHandler` + pub const SESSION_UI_REGISTERDIRECTAUTOMODESWITCHHANDLER: &str = + "session.ui.registerDirectAutoModeSwitchHandler"; + /// `session.ui.unregisterDirectAutoModeSwitchHandler` + pub const SESSION_UI_UNREGISTERDIRECTAUTOMODESWITCHHANDLER: &str = + "session.ui.unregisterDirectAutoModeSwitchHandler"; + /// `session.permissions.configure` + pub const SESSION_PERMISSIONS_CONFIGURE: &str = "session.permissions.configure"; /// `session.permissions.handlePendingPermissionRequest` pub const SESSION_PERMISSIONS_HANDLEPENDINGPERMISSIONREQUEST: &str = "session.permissions.handlePendingPermissionRequest"; + /// `session.permissions.pendingRequests` + pub const SESSION_PERMISSIONS_PENDINGREQUESTS: &str = "session.permissions.pendingRequests"; /// `session.permissions.setApproveAll` pub const SESSION_PERMISSIONS_SETAPPROVEALL: &str = "session.permissions.setApproveAll"; + /// `session.permissions.modifyRules` + pub const SESSION_PERMISSIONS_MODIFYRULES: &str = "session.permissions.modifyRules"; + /// `session.permissions.setRequired` + pub const SESSION_PERMISSIONS_SETREQUIRED: &str = "session.permissions.setRequired"; /// `session.permissions.resetSessionApprovals` pub const SESSION_PERMISSIONS_RESETSESSIONAPPROVALS: &str = "session.permissions.resetSessionApprovals"; + /// `session.permissions.notifyPromptShown` + pub const SESSION_PERMISSIONS_NOTIFYPROMPTSHOWN: &str = "session.permissions.notifyPromptShown"; + /// `session.permissions.paths.list` + pub const SESSION_PERMISSIONS_PATHS_LIST: &str = "session.permissions.paths.list"; + /// `session.permissions.paths.add` + pub const SESSION_PERMISSIONS_PATHS_ADD: &str = "session.permissions.paths.add"; + /// `session.permissions.paths.updatePrimary` + pub const SESSION_PERMISSIONS_PATHS_UPDATEPRIMARY: &str = + "session.permissions.paths.updatePrimary"; + /// `session.permissions.paths.isPathWithinAllowedDirectories` + pub const SESSION_PERMISSIONS_PATHS_ISPATHWITHINALLOWEDDIRECTORIES: &str = + "session.permissions.paths.isPathWithinAllowedDirectories"; + /// `session.permissions.paths.isPathWithinWorkspace` + pub const SESSION_PERMISSIONS_PATHS_ISPATHWITHINWORKSPACE: &str = + "session.permissions.paths.isPathWithinWorkspace"; + /// `session.permissions.urls.setUnrestrictedMode` + pub const SESSION_PERMISSIONS_URLS_SETUNRESTRICTEDMODE: &str = + "session.permissions.urls.setUnrestrictedMode"; /// `session.log` pub const SESSION_LOG: &str = "session.log"; + /// `session.metadata.snapshot` + pub const SESSION_METADATA_SNAPSHOT: &str = "session.metadata.snapshot"; + /// `session.metadata.isProcessing` + pub const SESSION_METADATA_ISPROCESSING: &str = "session.metadata.isProcessing"; + /// `session.metadata.contextInfo` + pub const SESSION_METADATA_CONTEXTINFO: &str = "session.metadata.contextInfo"; + /// `session.metadata.recordContextChange` + pub const SESSION_METADATA_RECORDCONTEXTCHANGE: &str = "session.metadata.recordContextChange"; + /// `session.metadata.setWorkingDirectory` + pub const SESSION_METADATA_SETWORKINGDIRECTORY: &str = "session.metadata.setWorkingDirectory"; + /// `session.metadata.recomputeContextTokens` + pub const SESSION_METADATA_RECOMPUTECONTEXTTOKENS: &str = + "session.metadata.recomputeContextTokens"; /// `session.shell.exec` pub const SESSION_SHELL_EXEC: &str = "session.shell.exec"; /// `session.shell.kill` @@ -164,12 +306,39 @@ pub mod rpc_methods { pub const SESSION_HISTORY_COMPACT: &str = "session.history.compact"; /// `session.history.truncate` pub const SESSION_HISTORY_TRUNCATE: &str = "session.history.truncate"; + /// `session.history.cancelBackgroundCompaction` + pub const SESSION_HISTORY_CANCELBACKGROUNDCOMPACTION: &str = + "session.history.cancelBackgroundCompaction"; + /// `session.history.abortManualCompaction` + pub const SESSION_HISTORY_ABORTMANUALCOMPACTION: &str = "session.history.abortManualCompaction"; + /// `session.history.summarizeForHandoff` + pub const SESSION_HISTORY_SUMMARIZEFORHANDOFF: &str = "session.history.summarizeForHandoff"; + /// `session.queue.pendingItems` + pub const SESSION_QUEUE_PENDINGITEMS: &str = "session.queue.pendingItems"; + /// `session.queue.removeMostRecent` + pub const SESSION_QUEUE_REMOVEMOSTRECENT: &str = "session.queue.removeMostRecent"; + /// `session.queue.clear` + pub const SESSION_QUEUE_CLEAR: &str = "session.queue.clear"; + /// `session.eventLog.read` + pub const SESSION_EVENTLOG_READ: &str = "session.eventLog.read"; + /// `session.eventLog.tail` + pub const SESSION_EVENTLOG_TAIL: &str = "session.eventLog.tail"; + /// `session.eventLog.registerInterest` + pub const SESSION_EVENTLOG_REGISTERINTEREST: &str = "session.eventLog.registerInterest"; + /// `session.eventLog.releaseInterest` + pub const SESSION_EVENTLOG_RELEASEINTEREST: &str = "session.eventLog.releaseInterest"; /// `session.usage.getMetrics` pub const SESSION_USAGE_GETMETRICS: &str = "session.usage.getMetrics"; /// `session.remote.enable` pub const SESSION_REMOTE_ENABLE: &str = "session.remote.enable"; /// `session.remote.disable` pub const SESSION_REMOTE_DISABLE: &str = "session.remote.disable"; + /// `session.remote.notifySteerableChanged` + pub const SESSION_REMOTE_NOTIFYSTEERABLECHANGED: &str = "session.remote.notifySteerableChanged"; + /// `session.schedule.list` + pub const SESSION_SCHEDULE_LIST: &str = "session.schedule.list"; + /// `session.schedule.stop` + pub const SESSION_SCHEDULE_STOP: &str = "session.schedule.stop"; /// `sessionFs.readFile` pub const SESSIONFS_READFILE: &str = "sessionFs.readFile"; /// `sessionFs.writeFile` @@ -196,6 +365,26 @@ pub mod rpc_methods { pub const SESSIONFS_SQLITEEXISTS: &str = "sessionFs.sqliteExists"; } +/// Parameters for aborting the current turn +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AbortRequest { + /// Finite reason code describing why the current turn was aborted + #[serde(skip_serializing_if = "Option::is_none")] + pub reason: Option, +} + +/// Result of aborting the current turn +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AbortResult { + /// Error message if the abort failed + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether the abort completed successfully + pub success: bool, +} + /// Optional GitHub token used to look up quota for a specific user instead of the global auth context. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -251,11 +440,31 @@ pub struct AgentInfo { pub description: String, /// Human-readable display name pub display_name: String, + /// Stable identifier for selection. For most agents this is the same as `name`; for plugin/builtin agents it may differ. Always populated; defaults to `name` when no distinct id was assigned. + pub id: String, + /// MCP server configurations attached to this agent, keyed by server name. Server config shape mirrors the MCP `mcpServers` schema. + #[serde(default)] + pub mcp_servers: HashMap, + /// Preferred model id for this agent. When omitted, inherits the outer agent's model. + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, /// Unique identifier of the custom agent pub name: String, /// Absolute local file path of the agent definition. Only set for file-based agents loaded from disk; remote agents do not have a path. #[serde(skip_serializing_if = "Option::is_none")] pub path: Option, + /// Skill names preloaded into this agent's context. Omitted means none. + #[serde(default)] + pub skills: Vec, + /// Where the agent definition was loaded from + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option, + /// Allowed tool names for this agent. Empty array means none; omitted means inherit defaults. + #[serde(default)] + pub tools: Vec, + /// Whether the agent can be selected directly by the user. Agents marked `false` are subagent-only. + #[serde(skip_serializing_if = "Option::is_none")] + pub user_invocable: Option, } /// The currently selected custom agent, or null when using the default agent. @@ -333,6 +542,236 @@ pub struct AgentSelectResult { pub agent: AgentInfo, } +/// Schema for the `CopilotUserResponseEndpoints` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponseEndpoints { + #[serde(skip_serializing_if = "Option::is_none")] + pub api: Option, + #[serde(rename = "origin-tracker", skip_serializing_if = "Option::is_none")] + pub origin_tracker: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub proxy: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub telemetry: Option, +} + +/// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponseQuotaSnapshotsChat { + #[serde(skip_serializing_if = "Option::is_none")] + pub entitlement: Option, + #[serde(rename = "has_quota", skip_serializing_if = "Option::is_none")] + pub has_quota: Option, + #[serde(rename = "overage_count", skip_serializing_if = "Option::is_none")] + pub overage_count: Option, + #[serde(rename = "overage_permitted", skip_serializing_if = "Option::is_none")] + pub overage_permitted: Option, + #[serde(rename = "percent_remaining", skip_serializing_if = "Option::is_none")] + pub percent_remaining: Option, + #[serde(rename = "quota_id", skip_serializing_if = "Option::is_none")] + pub quota_id: Option, + #[serde(rename = "quota_remaining", skip_serializing_if = "Option::is_none")] + pub quota_remaining: Option, + #[serde(rename = "quota_reset_at", skip_serializing_if = "Option::is_none")] + pub quota_reset_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining: Option, + #[serde(rename = "timestamp_utc", skip_serializing_if = "Option::is_none")] + pub timestamp_utc: Option, + #[serde( + rename = "token_based_billing", + skip_serializing_if = "Option::is_none" + )] + pub token_based_billing: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub unlimited: Option, +} + +/// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponseQuotaSnapshotsCompletions { + #[serde(skip_serializing_if = "Option::is_none")] + pub entitlement: Option, + #[serde(rename = "has_quota", skip_serializing_if = "Option::is_none")] + pub has_quota: Option, + #[serde(rename = "overage_count", skip_serializing_if = "Option::is_none")] + pub overage_count: Option, + #[serde(rename = "overage_permitted", skip_serializing_if = "Option::is_none")] + pub overage_permitted: Option, + #[serde(rename = "percent_remaining", skip_serializing_if = "Option::is_none")] + pub percent_remaining: Option, + #[serde(rename = "quota_id", skip_serializing_if = "Option::is_none")] + pub quota_id: Option, + #[serde(rename = "quota_remaining", skip_serializing_if = "Option::is_none")] + pub quota_remaining: Option, + #[serde(rename = "quota_reset_at", skip_serializing_if = "Option::is_none")] + pub quota_reset_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining: Option, + #[serde(rename = "timestamp_utc", skip_serializing_if = "Option::is_none")] + pub timestamp_utc: Option, + #[serde( + rename = "token_based_billing", + skip_serializing_if = "Option::is_none" + )] + pub token_based_billing: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub unlimited: Option, +} + +/// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponseQuotaSnapshotsPremiumInteractions { + #[serde(skip_serializing_if = "Option::is_none")] + pub entitlement: Option, + #[serde(rename = "has_quota", skip_serializing_if = "Option::is_none")] + pub has_quota: Option, + #[serde(rename = "overage_count", skip_serializing_if = "Option::is_none")] + pub overage_count: Option, + #[serde(rename = "overage_permitted", skip_serializing_if = "Option::is_none")] + pub overage_permitted: Option, + #[serde(rename = "percent_remaining", skip_serializing_if = "Option::is_none")] + pub percent_remaining: Option, + #[serde(rename = "quota_id", skip_serializing_if = "Option::is_none")] + pub quota_id: Option, + #[serde(rename = "quota_remaining", skip_serializing_if = "Option::is_none")] + pub quota_remaining: Option, + #[serde(rename = "quota_reset_at", skip_serializing_if = "Option::is_none")] + pub quota_reset_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining: Option, + #[serde(rename = "timestamp_utc", skip_serializing_if = "Option::is_none")] + pub timestamp_utc: Option, + #[serde( + rename = "token_based_billing", + skip_serializing_if = "Option::is_none" + )] + pub token_based_billing: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub unlimited: Option, +} + +/// Schema for the `CopilotUserResponseQuotaSnapshots` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponseQuotaSnapshots { + /// Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. + #[serde(skip_serializing_if = "Option::is_none")] + pub chat: Option, + /// Schema for the `CopilotUserResponseQuotaSnapshotsCompletions` type. + #[serde(skip_serializing_if = "Option::is_none")] + pub completions: Option, + /// Schema for the `CopilotUserResponseQuotaSnapshotsPremiumInteractions` type. + #[serde( + rename = "premium_interactions", + skip_serializing_if = "Option::is_none" + )] + pub premium_interactions: Option, +} + +/// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotUserResponse { + #[serde(rename = "access_type_sku", skip_serializing_if = "Option::is_none")] + pub access_type_sku: Option, + #[serde( + rename = "analytics_tracking_id", + skip_serializing_if = "Option::is_none" + )] + pub analytics_tracking_id: Option, + #[serde(rename = "assigned_date", skip_serializing_if = "Option::is_none")] + pub assigned_date: Option, + #[serde( + rename = "can_signup_for_limited", + skip_serializing_if = "Option::is_none" + )] + pub can_signup_for_limited: Option, + #[serde(rename = "chat_enabled", skip_serializing_if = "Option::is_none")] + pub chat_enabled: Option, + #[serde( + rename = "cli_remote_control_enabled", + skip_serializing_if = "Option::is_none" + )] + pub cli_remote_control_enabled: Option, + #[serde( + rename = "cloud_session_storage_enabled", + skip_serializing_if = "Option::is_none" + )] + pub cloud_session_storage_enabled: Option, + #[serde( + rename = "codex_agent_enabled", + skip_serializing_if = "Option::is_none" + )] + pub codex_agent_enabled: Option, + #[serde(rename = "copilot_plan", skip_serializing_if = "Option::is_none")] + pub copilot_plan: Option, + #[serde( + rename = "copilotignore_enabled", + skip_serializing_if = "Option::is_none" + )] + pub copilotignore_enabled: Option, + /// Schema for the `CopilotUserResponseEndpoints` type. + #[serde(skip_serializing_if = "Option::is_none")] + pub endpoints: Option, + #[serde(rename = "is_mcp_enabled", skip_serializing_if = "Option::is_none")] + pub is_mcp_enabled: Option, + #[serde(rename = "limited_user_quotas", default)] + pub limited_user_quotas: HashMap, + #[serde( + rename = "limited_user_reset_date", + skip_serializing_if = "Option::is_none" + )] + pub limited_user_reset_date: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub login: Option, + #[serde(rename = "monthly_quotas", default)] + pub monthly_quotas: HashMap, + #[serde(rename = "organization_list", skip_serializing_if = "Option::is_none")] + pub organization_list: Option, + #[serde(rename = "organization_login_list", default)] + pub organization_login_list: Vec, + #[serde(rename = "quota_reset_date", skip_serializing_if = "Option::is_none")] + pub quota_reset_date: Option, + #[serde( + rename = "quota_reset_date_utc", + skip_serializing_if = "Option::is_none" + )] + pub quota_reset_date_utc: Option, + /// Schema for the `CopilotUserResponseQuotaSnapshots` type. + #[serde(rename = "quota_snapshots", skip_serializing_if = "Option::is_none")] + pub quota_snapshots: Option, + #[serde( + rename = "restricted_telemetry", + skip_serializing_if = "Option::is_none" + )] + pub restricted_telemetry: Option, + #[serde( + rename = "token_based_billing", + skip_serializing_if = "Option::is_none" + )] + pub token_based_billing: Option, +} + +/// Schema for the `ApiKeyAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ApiKeyAuthInfo { + /// The API key. Treat as a secret. + pub api_key: String, + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Authentication host. + pub host: String, + /// API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style). + pub r#type: ApiKeyAuthInfoType, +} + /// Optional unstructured input hint #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -426,21 +865,21 @@ pub struct CommandsListRequest { pub include_skills: Option, } -/// Queued command request ID and the result indicating whether the client handled it. +/// Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommandsRespondToQueuedCommandRequest { - /// Request ID from the queued command event + /// Request ID from the `command.queued` event the host is responding to. pub request_id: RequestId, - /// Result of the queued command execution + /// Result of the queued command execution. pub result: serde_json::Value, } -/// Indicates whether the queued-command response was accepted by the session. +/// Indicates whether the queued-command response was matched to a pending request. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CommandsRespondToQueuedCommandResult { - /// Whether the response was accepted (false if the requestId was not found or already resolved) + /// Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. pub success: bool, } @@ -540,13 +979,29 @@ pub struct ConnectResult { pub version: String, } -/// The currently selected model for the session. +/// Schema for the `CopilotApiTokenAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CopilotApiTokenAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Authentication host (always the public GitHub host). + pub host: CopilotApiTokenAuthInfoHost, + /// Direct Copilot API authentication via the `GITHUB_COPILOT_API_TOKEN` + `COPILOT_API_URL` environment-variable pair. The token itself is read from the environment by the runtime, not carried in this struct. + pub r#type: CopilotApiTokenAuthInfoType, +} + +/// The currently selected model and reasoning effort for the session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CurrentModel { /// Currently active model identifier #[serde(skip_serializing_if = "Option::is_none")] pub model_id: Option, + /// Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. + #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning_effort: Option, } /// Schema for the `DiscoveredMcpServer` type. @@ -564,6 +1019,140 @@ pub struct DiscoveredMcpServer { pub r#type: Option, } +/// Slash-prefixed command string to enqueue for FIFO processing. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EnqueueCommandParams { + /// Slash-prefixed command string to enqueue, e.g. '/compact' or '/model gpt-4'. Queued FIFO with any in-flight items; if the session is idle, processing kicks off immediately. + pub command: String, +} + +/// Indicates whether the command was accepted into the local execution queue. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EnqueueCommandResult { + /// True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). + pub queued: bool, +} + +/// Schema for the `EnvAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EnvAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Name of the environment variable the token was sourced from. + pub env_var: String, + /// Authentication host (e.g. https://github.com or a GHES host). + pub host: String, + /// User login associated with the token. Undefined for server-to-server tokens (those starting with `ghs_`). + #[serde(skip_serializing_if = "Option::is_none")] + pub login: Option, + /// The token value itself. Treat as a secret. + pub token: String, + /// Personal access token (PAT) or server-to-server token sourced from an environment variable. + pub r#type: EnvAuthInfoType, +} + +/// Cursor, batch size, and optional long-poll/filter parameters for reading session events. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EventLogReadRequest { + /// Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. + #[serde(skip_serializing_if = "Option::is_none")] + pub agent_scope: Option, + /// Opaque cursor returned by a previous read. Omit on the first call to start from the beginning of the session's persisted history. + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + /// Maximum number of events to return in this batch (1–1000, default 200). + #[serde(skip_serializing_if = "Option::is_none")] + pub max: Option, + /// Either '*' to receive all event types, or a non-empty list of event types to receive + #[serde(skip_serializing_if = "Option::is_none")] + pub types: Option, + /// Milliseconds to wait for new events when the cursor is at the tail of history. 0 (default) returns immediately even if no events are available. Capped at 30000ms. Ephemeral events that arrive during the wait are delivered in this batch but are NOT replayable on a subsequent read (use a non-zero waitMs in your next call to capture future ephemerals as they happen). + #[serde(skip_serializing_if = "Option::is_none")] + pub wait_ms: Option, +} + +/// Indicates whether the operation succeeded. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EventLogReleaseInterestResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EventLogTailResult { + /// Opaque cursor pointing at the current tail of the session's persisted-events history. Pass back to `read` to receive only events that arrive AFTER this snapshot. When the session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent to omitting the cursor on a first read). + pub cursor: String, +} + +/// Batch of session events returned by a read, with cursor and continuation metadata. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EventsReadResult { + /// Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue from where this read left off. Always present, even when no events were returned. + pub cursor: String, + /// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. + pub cursor_status: EventsCursorStatus, + /// Events are delivered in two batches per read: persisted events first (in append order), then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral events do not interleave within a single read. + pub events: Vec, + /// True when the read returned `max` events and more events are available immediately. When false, the next read with a non-zero `waitMs` will block until a new event arrives or the wait expires. + pub has_more: bool, +} + +/// Slash command name and argument string to execute synchronously. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecuteCommandParams { + /// Argument string to pass to the command (empty string if none). + pub args: String, + /// Name of the slash command to invoke (without the leading '/'). + pub command_name: String, +} + +/// Error message produced while executing the command, if any. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExecuteCommandResult { + /// Error message produced while executing the command, if any. Omitted when the handler succeeded. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, +} + /// Schema for the `Extension` type. /// ///
@@ -742,7 +1331,7 @@ pub struct ExternalToolTextResultForLlmContentResourceLink { pub name: String, /// Size of the resource in bytes #[serde(skip_serializing_if = "Option::is_none")] - pub size: Option, + pub size: Option, /// Human-readable display title for the resource #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, @@ -761,7 +1350,7 @@ pub struct ExternalToolTextResultForLlmContentTerminal { pub cwd: Option, /// Process exit code, if the command has completed #[serde(skip_serializing_if = "Option::is_none")] - pub exit_code: Option, + pub exit_code: Option, /// Terminal/shell output text pub text: String, /// Content block type discriminator @@ -809,6 +1398,23 @@ pub struct FleetStartResult { pub started: bool, } +/// Schema for the `GhCliAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GhCliAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Authentication host. + pub host: String, + /// User login as reported by `gh auth status`. + pub login: String, + /// The token returned by `gh auth token`. Treat as a secret. + pub token: String, + /// Authentication via the `gh` CLI's saved credentials. + pub r#type: GhCliAuthInfoType, +} + /// Pending external tool call request ID, with the tool result or an error describing why it failed. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -831,6 +1437,36 @@ pub struct HandlePendingToolCallResult { pub success: bool, } +/// Indicates whether an in-progress manual compaction was aborted. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HistoryAbortManualCompactionResult { + /// Whether an in-progress manual compaction was aborted. False when no manual compaction was running, when its abort controller was already aborted, or when the session is remote. + pub aborted: bool, +} + +/// Indicates whether an in-progress background compaction was cancelled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HistoryCancelBackgroundCompactionResult { + /// Whether an in-progress background compaction was cancelled. False when no compaction was running, when the session is remote, or when the underlying processor was unavailable. + pub cancelled: bool, +} + /// Post-compaction context window usage breakdown /// ///
@@ -859,7 +1495,7 @@ pub struct HistoryCompactContextWindow { pub tool_definitions_tokens: Option, } -/// Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. +/// Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. /// ///
/// @@ -877,10 +1513,28 @@ pub struct HistoryCompactResult { pub messages_removed: i64, /// Whether compaction completed successfully pub success: bool, + /// Summary text produced by compaction. Omitted when compaction did not produce a summary (e.g. failure path). + #[serde(skip_serializing_if = "Option::is_none")] + pub summary_content: Option, /// Number of tokens freed by compaction pub tokens_removed: i64, } +/// Markdown summary of the conversation context (empty when not available). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HistorySummarizeForHandoffResult { + /// Markdown summary of the conversation context produced by an LLM. Empty string when there are no messages or when the session does not support local summarization. + pub summary: String, +} + /// Identifier of the event to truncate to; this event and all later events are removed. /// ///
@@ -911,39 +1565,144 @@ pub struct HistoryTruncateResult { pub events_removed: i64, } -/// Schema for the `InstructionsSources` type. +/// Schema for the `HMACAuthInfo` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct InstructionsSources { - /// Glob pattern from frontmatter — when set, this instruction applies only to matching files - #[serde(skip_serializing_if = "Option::is_none")] - pub apply_to: Option, - /// Raw content of the instruction file - pub content: String, - /// Short description (body after frontmatter) for use in instruction tables +pub struct HMACAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Unique identifier for this source (used for toggling) - pub id: String, - /// Human-readable label - pub label: String, - /// Where this source lives — used for UI grouping - pub location: InstructionsSourcesLocation, - /// File path relative to repo or absolute for home - pub source_path: String, - /// Category of instruction source — used for merge logic - pub r#type: InstructionsSourcesType, + pub copilot_user: Option, + /// HMAC secret used to sign requests. + pub hmac: String, + /// Authentication host. HMAC auth always targets the public GitHub host. + pub host: HMACAuthInfoHost, + /// HMAC-based authentication used by GitHub-internal services. + pub r#type: HMACAuthInfoType, } -/// Instruction sources loaded for the session, in merge order. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InstructionsGetSourcesResult { - /// Instruction sources for the session +/// Schema for the `InstalledPlugin` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstalledPlugin { + /// Path where the plugin is cached locally + #[serde(rename = "cache_path", skip_serializing_if = "Option::is_none")] + pub cache_path: Option, + /// Whether the plugin is currently enabled + pub enabled: bool, + /// Installation timestamp + #[serde(rename = "installed_at")] + pub installed_at: String, + /// Marketplace the plugin came from (empty string for direct repo installs) + pub marketplace: String, + /// Plugin name + pub name: String, + /// Source for direct repo installs (when marketplace is empty) + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option, + /// Version installed (if available) + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} + +/// Schema for the `InstalledPluginSourceGithub` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstalledPluginSourceGithub { + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + pub repo: String, + /// Constant value. Always "github". + pub source: InstalledPluginSourceGithubSource, +} + +/// Schema for the `InstalledPluginSourceLocal` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstalledPluginSourceLocal { + pub path: String, + /// Constant value. Always "local". + pub source: InstalledPluginSourceLocalSource, +} + +/// Schema for the `InstalledPluginSourceUrl` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstalledPluginSourceUrl { + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + /// Constant value. Always "url". + pub source: InstalledPluginSourceUrlSource, + pub url: String, +} + +/// Schema for the `InstructionsSources` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstructionsSources { + /// Glob pattern(s) from frontmatter — when set, this instruction applies only to matching files + #[serde(default)] + pub apply_to: Vec, + /// Raw content of the instruction file + pub content: String, + /// When true, this source starts disabled and must be toggled on by the user + #[serde(skip_serializing_if = "Option::is_none")] + pub default_disabled: Option, + /// Short description (body after frontmatter) for use in instruction tables + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Unique identifier for this source (used for toggling) + pub id: String, + /// Human-readable label + pub label: String, + /// Where this source lives — used for UI grouping + pub location: InstructionsSourcesLocation, + /// File path relative to repo or absolute for home + pub source_path: String, + /// Category of instruction source — used for merge logic + pub r#type: InstructionsSourcesType, +} + +/// Instruction sources loaded for the session, in merge order. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstructionsGetSourcesResult { + /// Instruction sources for the session pub sources: Vec, } -/// Message text, optional severity level, persistence flag, and optional follow-up URL. +/// Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct LogRequest { @@ -955,6 +1714,12 @@ pub struct LogRequest { pub level: Option, /// Human-readable message pub message: String, + /// Optional actionable tip displayed alongside the message. Only honored on `level: "info"`. + #[serde(skip_serializing_if = "Option::is_none")] + pub tip: Option, + /// Domain category for this log entry (e.g., "mcp", "subscription", "policy", "model"). Maps to `infoType`/`warningType`/`errorType` on the emitted event. Defaults to "notification". + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option, /// Optional URL the user can open in their browser for more details #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, @@ -968,6 +1733,58 @@ pub struct LogResult { pub event_id: String, } +/// Parameters for (re)loading the merged LSP configuration set. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct LspInitializeRequest { + /// Force re-initialization even when LSP configs were already loaded for the working directory. + #[serde(skip_serializing_if = "Option::is_none")] + pub force: Option, + /// Git root used as the boundary when traversing for project-level LSP configs (supports monorepos). + #[serde(skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Working directory used to load project-level LSP configs. Defaults to the session working directory when omitted. + #[serde(skip_serializing_if = "Option::is_none")] + pub working_directory: Option, +} + +/// The requestId previously passed to executeSampling that should be cancelled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpCancelSamplingExecutionParams { + /// The requestId previously passed to executeSampling that should be cancelled + pub request_id: RequestId, +} + +/// Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpCancelSamplingExecutionResult { + /// True if an in-flight execution with the given requestId was found and signalled to cancel. False when no such execution is in flight (already completed, never started, or cancelled by another caller). + pub cancelled: bool, +} + /// MCP server name and configuration to add to user configuration. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -1067,6 +1884,51 @@ pub struct McpEnableRequest { pub server_name: String, } +/// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpExecuteSamplingRequest {} + +/// Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpExecuteSamplingParams { + /// The original MCP JSON-RPC request ID (string or number). Used by the runtime to correlate the inference with the originating MCP request for telemetry; this is distinct from `requestId` (which is the schema-level cancellation handle). + pub mcp_request_id: serde_json::Value, + /// Raw MCP CreateMessageRequest params, as received in the `sampling.requested` event. Treated as opaque at the schema layer; the runtime converts the embedded MCP messages into the OpenAI chat-completion shape internally. + pub request: McpExecuteSamplingRequest, + /// Caller-provided unique identifier for this sampling execution. Use this same ID with cancelSamplingExecution to cancel the in-flight call. Must be unique within the session for the lifetime of the call. + pub request_id: RequestId, + /// Name of the MCP server that initiated the sampling request + pub server_name: String, +} + +/// MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpExecuteSamplingResult {} + /// Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. /// ///
@@ -1107,6 +1969,42 @@ pub struct McpOauthLoginResult { pub authorization_url: Option, } +/// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpRemoveGitHubResult { + /// True when the auto-managed `github` MCP server was removed; false when no removal happened (e.g. user has explicitly configured a `github` server, or the server was not registered). + pub removed: bool, +} + +/// Outcome of an MCP sampling execution: success result, failure error, or cancellation. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpSamplingExecutionResult { + /// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. + pub action: McpSamplingExecutionAction, + /// Error description, present when action='failure'. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. + #[serde(skip_serializing_if = "Option::is_none")] + pub result: Option, +} + /// Schema for the `McpServer` type. /// ///
@@ -1221,55 +2119,329 @@ pub struct McpServerList { pub servers: Vec, } -/// Token-level pricing information for this model +/// Mode controlling how MCP server env values are resolved (`direct` or `indirect`). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ModelBillingTokenPrices { - /// Number of tokens per standard billing batch - #[serde(skip_serializing_if = "Option::is_none")] - pub batch_size: Option, - /// Price per billing batch of cached tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) - #[serde(skip_serializing_if = "Option::is_none")] - pub cache_price: Option, - /// Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) - #[serde(skip_serializing_if = "Option::is_none")] - pub input_price: Option, - /// Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) - #[serde(skip_serializing_if = "Option::is_none")] - pub output_price: Option, +pub struct McpSetEnvValueModeParams { + /// How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". + pub mode: McpSetEnvValueModeDetails, } -/// Billing information +/// Env-value mode recorded on the session after the update. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ModelBilling { - /// Billing cost multiplier relative to the base rate - #[serde(skip_serializing_if = "Option::is_none")] - pub multiplier: Option, - /// Token-level pricing information for this model +pub struct McpSetEnvValueModeResult { + /// Mode recorded on the session after the update + pub mode: McpSetEnvValueModeDetails, +} + +/// Model identifier and token limits used to compute the context-info breakdown. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataContextInfoRequest { + /// Maximum output tokens allowed by the target model. Pass 0 if unknown. + pub output_token_limit: i64, + /// Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. + pub prompt_token_limit: i64, + /// Model identifier used for tokenization. Omit to use the session default. Used both for token counting and to compute display values. #[serde(skip_serializing_if = "Option::is_none")] - pub token_prices: Option, + pub selected_model: Option, } -/// Vision-specific limits +/// Token-usage breakdown for the session's current context window #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ModelCapabilitiesLimitsVision { - /// Maximum image size in bytes - #[serde(rename = "max_prompt_image_size")] - pub max_prompt_image_size: i64, - /// Maximum number of images per prompt - #[serde(rename = "max_prompt_images")] - pub max_prompt_images: i64, - /// MIME types the model accepts - #[serde(rename = "supported_media_types")] - pub supported_media_types: Vec, +pub struct MetadataContextInfoResultContextInfo { + /// Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%) + pub buffer_tokens: i64, + /// Token count at which background compaction starts (configurable percentage of promptTokenLimit) + pub compaction_threshold: i64, + /// Tokens consumed by user/assistant/tool messages + pub conversation_tokens: i64, + /// Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. + pub limit: i64, + /// The model used for token counting + pub model_name: String, + /// Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified) + pub prompt_token_limit: i64, + /// Tokens consumed by the system prompt + pub system_tokens: i64, + /// Tokens consumed by tool definitions sent to the model (excludes deferred tools) + pub tool_definitions_tokens: i64, + /// Sum of system, conversation and tool-definition tokens + pub total_tokens: i64, } -/// Token limits for prompts, outputs, and context window +/// Token breakdown for the session's current context window, or null if uninitialized. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ModelCapabilitiesLimits { +pub struct MetadataContextInfoResult { + /// Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). + pub context_info: Option, +} + +/// Indicates whether the local session is currently processing a turn or background continuation. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataIsProcessingResult { + /// Whether the session is currently processing user/agent messages. False for non-local sessions (which don't run a local agentic loop). Reflects an in-flight turn or background continuation. + pub processing: bool, +} + +/// Model identifier to use when re-tokenizing the session's existing messages. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataRecomputeContextTokensRequest { + /// Model identifier used for tokenization. The runtime token-counts both chat-context and system-context messages against this model. + pub model_id: String, +} + +/// Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataRecomputeContextTokensResult { + /// Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). + pub messages_token_count: i64, + /// Tokens contributed by system/developer prompt snapshots. + pub system_token_count: i64, + /// Sum of tokens across chat-context and system-context messages currently held by the session. + pub total_tokens: i64, +} + +/// Updated working directory and git context. Emitted as the new payload of `session.context_changed`. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkingDirectoryContext { + /// Merge-base commit SHA (fork point from the remote default branch) + #[serde(skip_serializing_if = "Option::is_none")] + pub base_commit: Option, + /// Current git branch name + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + /// Current working directory path + pub cwd: String, + /// Root directory of the git repository, resolved via git rev-parse + #[serde(skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Head commit of the current git branch + #[serde(skip_serializing_if = "Option::is_none")] + pub head_commit: Option, + /// Hosting platform type of the repository + #[serde(skip_serializing_if = "Option::is_none")] + pub host_type: Option, + /// Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps) + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + /// Raw host string from the git remote URL (e.g. "github.com", "dev.azure.com") + #[serde(skip_serializing_if = "Option::is_none")] + pub repository_host: Option, +} + +/// Updated working-directory/git context to record on the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataRecordContextChangeRequest { + /// Updated working directory and git context. Emitted as the new payload of `session.context_changed`. + pub context: SessionWorkingDirectoryContext, +} + +/// Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataRecordContextChangeResult {} + +/// Absolute path to set as the session's new working directory. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataSetWorkingDirectoryRequest { + /// Absolute path to set as the session's working directory. The runtime updates the session's recorded cwd so subsequent operations (shell tools, file lookups, telemetry) anchor to it. + pub working_directory: String, +} + +/// Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataSetWorkingDirectoryResult { + /// Working directory after the update + pub working_directory: String, +} + +/// The repository the remote session targets. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataSnapshotRemoteMetadataRepository { + /// The branch the remote session is operating on. + pub branch: String, + /// The GitHub repository name (without owner). + pub name: String, + /// The GitHub owner (user or organization) of the target repository. + pub owner: String, +} + +/// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MetadataSnapshotRemoteMetadata { + /// The pull request number the remote session is associated with, if any. + #[serde(skip_serializing_if = "Option::is_none")] + pub pull_request_number: Option, + /// The repository the remote session targets. + pub repository: MetadataSnapshotRemoteMetadataRepository, + /// The original resource identifier (task ID or PR node ID), preserved across event-replay reconstructions. Falls back to `sessionId` when absent. + #[serde(skip_serializing_if = "Option::is_none")] + pub resource_id: Option, + /// Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` invocation. + #[serde(skip_serializing_if = "Option::is_none")] + pub task_type: Option, +} + +/// Token-level pricing information for this model +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelBillingTokenPrices { + /// Number of tokens per standard billing batch + #[serde(skip_serializing_if = "Option::is_none")] + pub batch_size: Option, + /// Price per billing batch of cached tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) + #[serde(skip_serializing_if = "Option::is_none")] + pub cache_price: Option, + /// Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) + #[serde(skip_serializing_if = "Option::is_none")] + pub input_price: Option, + /// Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD) + #[serde(skip_serializing_if = "Option::is_none")] + pub output_price: Option, +} + +/// Billing information +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelBilling { + /// Billing cost multiplier relative to the base rate + #[serde(skip_serializing_if = "Option::is_none")] + pub multiplier: Option, + /// Token-level pricing information for this model + #[serde(skip_serializing_if = "Option::is_none")] + pub token_prices: Option, +} + +/// Vision-specific limits +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelCapabilitiesLimitsVision { + /// Maximum image size in bytes + #[serde(rename = "max_prompt_image_size")] + pub max_prompt_image_size: i64, + /// Maximum number of images per prompt + #[serde(rename = "max_prompt_images")] + pub max_prompt_images: i64, + /// MIME types the model accepts + #[serde(rename = "supported_media_types")] + pub supported_media_types: Vec, +} + +/// Token limits for prompts, outputs, and context window +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelCapabilitiesLimits { /// Maximum total context window size in tokens #[serde( rename = "max_context_window_tokens", @@ -1423,6 +2595,22 @@ pub struct ModelList { pub models: Vec, } +/// Reasoning effort level to apply to the currently selected model. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelSetReasoningEffortRequest { + /// Reasoning effort level to apply to the currently selected model. The host is responsible for validating the value against the model's supported levels before calling. + pub reasoning_effort: String, +} + +/// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelSetReasoningEffortResult { + /// Reasoning effort level recorded on the session after the update + pub reasoning_effort: String, +} + /// Optional GitHub token used to list models for a specific user instead of the global auth context. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -1474,6 +2662,22 @@ pub struct NameGetResult { pub name: Option, } +/// Auto-generated session summary to apply as the session's name when no user-set name exists. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NameSetAutoRequest { + /// Auto-generated session summary. Empty/whitespace-only values are ignored; values are trimmed before persisting. + pub summary: String, +} + +/// Indicates whether the auto-generated summary was applied as the session's name. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NameSetAutoResult { + /// Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. + pub applied: bool, +} + /// New friendly name to apply to the session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -1482,11 +2686,29 @@ pub struct NameSetRequest { pub name: String, } +/// Schema for the `PendingPermissionRequest` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PendingPermissionRequest { + /// The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook) + pub request: PermissionPromptRequest, + /// Unique identifier for the pending permission request + pub request_id: RequestId, +} + +/// List of pending permission requests reconstructed from event history. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PendingPermissionRequestList { + /// Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. + pub items: Vec, +} + /// Schema for the `PermissionDecisionApproveOnce` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApproveOnce { - /// The permission request was approved for this one instance + /// Approve this single request only pub kind: PermissionDecisionApproveOnceKind, } @@ -1581,13 +2803,13 @@ pub struct PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApproveForSession { - /// The approval to add as a session-scoped rule + /// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) #[serde(skip_serializing_if = "Option::is_none")] pub approval: Option, - /// The URL domain to approve for this session + /// URL domain to approve for the rest of the session (URL prompts only) #[serde(skip_serializing_if = "Option::is_none")] pub domain: Option, - /// Approved and remembered for the rest of the session + /// Approve and remember for the rest of the session pub kind: PermissionDecisionApproveForSessionKind, } @@ -1682,11 +2904,11 @@ pub struct PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApproveForLocation { - /// The approval to persist for this location + /// Approval to persist for this location pub approval: PermissionDecisionApproveForLocationApproval, - /// Approved and persisted for this project location + /// Approve and persist for this project location pub kind: PermissionDecisionApproveForLocationKind, - /// The location key (git root or cwd) to persist the approval to + /// Location key (git root or cwd) to persist the approval to pub location_key: String, } @@ -1694,9 +2916,9 @@ pub struct PermissionDecisionApproveForLocation { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApprovePermanently { - /// The URL domain to approve permanently + /// URL domain to approve permanently pub domain: String, - /// Approved and persisted across sessions + /// Approve and persist across sessions (URL prompts only) pub kind: PermissionDecisionApprovePermanentlyKind, } @@ -1704,10 +2926,10 @@ pub struct PermissionDecisionApprovePermanently { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionReject { - /// Optional feedback from the user explaining the denial + /// Optional feedback explaining the rejection #[serde(skip_serializing_if = "Option::is_none")] pub feedback: Option, - /// Denied by the user during an interactive prompt + /// Reject the request pub kind: PermissionDecisionRejectKind, } @@ -1715,76 +2937,440 @@ pub struct PermissionDecisionReject { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionUserNotAvailable { - /// Denied because user confirmation was unavailable + /// No user is available to confirm the request pub kind: PermissionDecisionUserNotAvailableKind, } -/// Pending permission request ID and the decision to apply (approve/reject and scope). -#[derive(Debug, Clone, Serialize, Deserialize)] +/// Schema for the `PermissionDecisionApproved` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionDecisionRequest { - /// Request ID of the pending permission request - pub request_id: RequestId, - /// Decision to apply to a pending permission request. - pub result: PermissionDecision, +pub struct PermissionDecisionApproved { + /// The permission request was approved + pub kind: PermissionDecisionApprovedKind, } -/// Indicates whether the permission decision was applied; false when the request was already resolved. +/// Schema for the `PermissionDecisionApprovedForSession` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionRequestResult { - /// Whether the permission request was handled successfully - pub success: bool, +pub struct PermissionDecisionApprovedForSession { + /// The approval to add as a session-scoped rule + pub approval: UserToolSessionApproval, + /// Approved and remembered for the rest of the session + pub kind: PermissionDecisionApprovedForSessionKind, } -/// No parameters; clears all session-scoped tool permission approvals. +/// Schema for the `PermissionDecisionApprovedForLocation` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionsResetSessionApprovalsRequest {} +pub struct PermissionDecisionApprovedForLocation { + /// The approval to persist for this location + pub approval: UserToolSessionApproval, + /// Approved and persisted for this project location + pub kind: PermissionDecisionApprovedForLocationKind, + /// The location key (git root or cwd) to persist the approval to + pub location_key: String, +} -/// Indicates whether the operation succeeded. +/// Schema for the `PermissionDecisionCancelled` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionsResetSessionApprovalsResult { - /// Whether the operation succeeded - pub success: bool, +pub struct PermissionDecisionCancelled { + /// The permission request was cancelled before a response was used + pub kind: PermissionDecisionCancelledKind, + /// Optional explanation of why the request was cancelled + #[serde(skip_serializing_if = "Option::is_none")] + pub reason: Option, } -/// Whether to auto-approve all tool permission requests for the rest of the session. +/// Schema for the `PermissionDecisionDeniedByRules` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionsSetApproveAllRequest { - /// Whether to auto-approve all tool permission requests - pub enabled: bool, +pub struct PermissionDecisionDeniedByRules { + /// Denied because approval rules explicitly blocked it + pub kind: PermissionDecisionDeniedByRulesKind, + /// Rules that denied the request + pub rules: Vec, } -/// Indicates whether the operation succeeded. +/// Schema for the `PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PermissionsSetApproveAllResult { - /// Whether the operation succeeded - pub success: bool, +pub struct PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser { + /// Denied because no approval rule matched and user confirmation was unavailable + pub kind: PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind, } -/// Optional message to echo back to the caller. +/// Schema for the `PermissionDecisionDeniedInteractivelyByUser` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PingRequest { - /// Optional message to echo back +pub struct PermissionDecisionDeniedInteractivelyByUser { + /// Optional feedback from the user explaining the denial #[serde(skip_serializing_if = "Option::is_none")] - pub message: Option, + pub feedback: Option, + /// Whether to force-reject the current agent turn + #[serde(skip_serializing_if = "Option::is_none")] + pub force_reject: Option, + /// Denied by the user during an interactive prompt + pub kind: PermissionDecisionDeniedInteractivelyByUserKind, } -/// Server liveness response, including the echoed message, current timestamp, and protocol version. +/// Schema for the `PermissionDecisionDeniedByContentExclusionPolicy` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct PingResult { - /// Echoed message (or default greeting) +pub struct PermissionDecisionDeniedByContentExclusionPolicy { + /// Denied by the organization's content exclusion policy + pub kind: PermissionDecisionDeniedByContentExclusionPolicyKind, + /// Human-readable explanation of why the path was excluded pub message: String, - /// Server protocol version number - pub protocol_version: i64, - /// Server timestamp in milliseconds - pub timestamp: i64, + /// File path that triggered the exclusion + pub path: String, +} + +/// Schema for the `PermissionDecisionDeniedByPermissionRequestHook` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionDecisionDeniedByPermissionRequestHook { + /// Whether to interrupt the current agent turn + #[serde(skip_serializing_if = "Option::is_none")] + pub interrupt: Option, + /// Denied by a permission request hook registered by an extension or plugin + pub kind: PermissionDecisionDeniedByPermissionRequestHookKind, + /// Optional message from the hook explaining the denial + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, +} + +/// Pending permission request ID and the decision to apply (approve/reject and scope). +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionDecisionRequest { + /// Request ID of the pending permission request + pub request_id: RequestId, + /// The client's response to the pending permission prompt + pub result: PermissionDecision, +} + +/// Directory path to add to the session's allowed directories. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsAddParams { + /// Directory to add to the allow-list. The runtime resolves and validates the path before adding. + pub path: String, +} + +/// Path to evaluate against the session's allowed directories. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsAllowedCheckParams { + /// Path to check against the session's allowed directories + pub path: String, +} + +/// Indicates whether the supplied path is within the session's allowed directories. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsAllowedCheckResult { + /// Whether the path is within the session's allowed directories + pub allowed: bool, +} + +/// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsConfig { + /// Additional directories to allow tool access to (in addition to the session's working directory). When `unrestricted` is true, these are still pre-populated on the UnrestrictedPathManager so they remain visible via getDirectories() (e.g. for @-mention completion). + #[serde(default)] + pub additional_directories: Vec, + /// Whether to include the system temp directory in the allowed list (defaults to true). Ignored when `unrestricted` is true. + #[serde(skip_serializing_if = "Option::is_none")] + pub include_temp_directory: Option, + /// If true, the runtime allows access to all paths without prompting. Equivalent to constructing an UnrestrictedPathManager. + #[serde(skip_serializing_if = "Option::is_none")] + pub unrestricted: Option, + /// Workspace root path (special-cased to be allowed even before the directory exists). Ignored when `unrestricted` is true. + #[serde(skip_serializing_if = "Option::is_none")] + pub workspace_path: Option, +} + +/// Snapshot of the session's allow-listed directories and primary working directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsList { + /// All directories currently allowed for tool access on this session. + pub directories: Vec, + /// The primary working directory for this session. + pub primary: String, +} + +/// Directory path to set as the session's new primary working directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsUpdatePrimaryParams { + /// Directory to set as the new primary working directory for the session's permission policy. + pub path: String, +} + +/// Path to evaluate against the session's workspace (primary) directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsWorkspaceCheckParams { + /// Path to check against the session workspace directory + pub path: String, +} + +/// Indicates whether the supplied path is within the session's workspace directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPathsWorkspaceCheckResult { + /// Whether the path is within the session workspace directory + pub allowed: bool, +} + +/// Notification payload describing the permission prompt that the client just rendered. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionPromptShownNotification { + /// Human-readable description of the prompt the user is being asked to approve. Used by the runtime to fire the registered `permission_prompt` notification hook (e.g. terminal bell, desktop notification). + pub message: String, +} + +/// Indicates whether the permission decision was applied; false when the request was already resolved. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionRequestResult { + /// Whether the permission request was handled successfully + pub success: bool, +} + +/// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionRulesSet { + /// Rules that auto-approve matching requests + pub approved: Vec, + /// Rules that auto-deny matching requests + pub denied: Vec, +} + +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsConfigureAdditionalContentExclusionPolicyRuleSource { + pub name: String, + pub r#type: String, +} + +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsConfigureAdditionalContentExclusionPolicyRule { + #[serde(default)] + pub if_any_match: Vec, + #[serde(default)] + pub if_none_match: Vec, + pub paths: Vec, + /// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. + pub source: PermissionsConfigureAdditionalContentExclusionPolicyRuleSource, +} + +/// Schema for the `PermissionsConfigureAdditionalContentExclusionPolicy` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsConfigureAdditionalContentExclusionPolicy { + #[serde(rename = "last_updated_at")] + pub last_updated_at: serde_json::Value, + pub rules: Vec, + /// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. + pub scope: PermissionsConfigureAdditionalContentExclusionPolicyScope, +} + +/// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionUrlsConfig { + /// Initial list of allowed URL/domain patterns. Patterns may include path components. Ignored when `unrestricted` is true. + #[serde(default)] + pub initial_allowed: Vec, + /// If true, the runtime allows access to all URLs without prompting. Initial allow-list is ignored when this is true. + #[serde(skip_serializing_if = "Option::is_none")] + pub unrestricted: Option, +} + +/// Patch of permission policy fields to apply (omit a field to leave it unchanged). +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsConfigureParams { + /// If specified, replaces the host-supplied GitHub Content Exclusion policies on the session (combined with natively-discovered policies when evaluating tool/file access). Omit to leave the current policies unchanged. + #[serde(default)] + pub additional_content_exclusion_policies: + Vec, + /// If specified, sets whether path/URL read permission requests are auto-approved. Omit to leave the current value unchanged. + #[serde(skip_serializing_if = "Option::is_none")] + pub approve_all_read_permission_requests: Option, + /// If specified, sets whether tool permission requests are auto-approved without prompting. Omit to leave the current value unchanged. + #[serde(skip_serializing_if = "Option::is_none")] + pub approve_all_tool_permission_requests: Option, + /// If specified, replaces the session's path-permission policy. The runtime constructs the appropriate PathManager based on these inputs (rooted at the session's working directory). Omit to leave the current path policy unchanged. + #[serde(skip_serializing_if = "Option::is_none")] + pub paths: Option, + /// If specified, replaces the session's approved/denied permission rules. Omit to leave the current rules unchanged. + #[serde(skip_serializing_if = "Option::is_none")] + pub rules: Option, + /// If specified, replaces the session's URL-permission policy. The runtime constructs a fresh DefaultUrlManager based on these inputs. Omit to leave the current URL policy unchanged. + #[serde(skip_serializing_if = "Option::is_none")] + pub urls: Option, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsConfigureResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Scope and add/remove instructions for modifying session- or location-scoped permission rules. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsModifyRulesParams { + /// Rules to add to the scope. Applied before `remove`/`removeAll`. + #[serde(default)] + pub add: Vec, + /// Specific rules to remove from the scope. Ignored when `removeAll` is true. + #[serde(default)] + pub remove: Vec, + /// When true, removes every rule currently in the scope (after any `add` is applied). Useful for clearing the location scope wholesale. + #[serde(skip_serializing_if = "Option::is_none")] + pub remove_all: Option, + /// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. + pub scope: PermissionsModifyRulesScope, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsModifyRulesResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsNotifyPromptShownResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsPathsAddResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// No parameters; returns the session's allow-listed directories. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsPathsListRequest {} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsPathsUpdatePrimaryResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// No parameters; returns currently-pending permission requests for the session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsPendingRequestsRequest {} + +/// No parameters; clears all session-scoped tool permission approvals. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsResetSessionApprovalsRequest {} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsResetSessionApprovalsResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Allow-all toggle for tool permission requests, with an optional telemetry source. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsSetApproveAllRequest { + /// Whether to auto-approve all tool permission requests + pub enabled: bool, + /// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsSetApproveAllResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Toggles whether permission prompts should be bridged into session events for this client. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsSetRequiredRequest { + /// Whether the client wants `permission.requested` events bridged from the session-owned permission service. CLI clients that render prompt UI set this to `true` for as long as their listener is mounted; headless callers leave it unset (the default is `false`). + pub required: bool, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsSetRequiredResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Indicates whether the operation succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionsUrlsSetUnrestrictedModeResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Whether the URL-permission policy should run in unrestricted mode. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PermissionUrlsSetUnrestrictedModeParams { + /// Whether to allow access to all URLs without prompting. Toggles the runtime's URL-permission policy in place. + pub enabled: bool, +} + +/// Optional message to echo back to the caller. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PingRequest { + /// Optional message to echo back + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, +} + +/// Server liveness response, including the echoed message, current server timestamp, and protocol version. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PingResult { + /// Echoed message (or default greeting) + pub message: String, + /// Server protocol version number + pub protocol_version: i64, + /// ISO 8601 timestamp when the server handled the ping + pub timestamp: String, } /// Existence, contents, and resolved path of the session plan file. @@ -1848,9 +3434,9 @@ pub struct PluginList { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct QueuedCommandHandled { - /// The command was handled + /// The host actually executed the queued command. pub handled: bool, - /// If true, stop processing remaining queued items + /// When true, the runtime will not process subsequent queued commands until a new request comes in. #[serde(skip_serializing_if = "Option::is_none")] pub stop_processing_queue: Option, } @@ -1859,11 +3445,11 @@ pub struct QueuedCommandHandled { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct QueuedCommandNotHandled { - /// The command was not handled + /// The host did not execute the queued command. Unblocks the queue without claiming the command was processed (e.g. when the handler threw before completing). pub handled: bool, } -/// Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. +/// Schema for the `QueuePendingItems` type. /// ///
/// @@ -1873,13 +3459,14 @@ pub struct QueuedCommandNotHandled { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RemoteEnableRequest { - /// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. - #[serde(skip_serializing_if = "Option::is_none")] - pub mode: Option, +pub struct QueuePendingItems { + /// Human-readable text to display for this queue entry in the UI + pub display_text: String, + /// Whether this item is a queued user message or a queued slash command / model change + pub kind: QueuePendingItemsKind, } -/// GitHub URL for the session and a flag indicating whether remote steering is enabled. +/// Snapshot of the session's pending queued items and immediate-steering messages. /// ///
/// @@ -1889,15 +3476,14 @@ pub struct RemoteEnableRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RemoteEnableResult { - /// Whether remote steering is enabled - pub remote_steerable: bool, - /// GitHub frontend URL for this session - #[serde(skip_serializing_if = "Option::is_none")] - pub url: Option, +pub struct QueuePendingItemsResult { + /// Pending queued items in submission order. Includes user messages, queued slash commands, and queued model changes; omits internal system items. + pub items: Vec, + /// Display text for messages currently in the immediate steering queue (interjections sent during a running turn). + pub steering_messages: Vec, } -/// Remote session connection result. +/// Indicates whether a user-facing pending item was removed. /// ///
/// @@ -1907,345 +3493,428 @@ pub struct RemoteEnableResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RemoteSessionConnectionResult { - /// Metadata for a connected remote session. - pub metadata: ConnectedRemoteSessionMetadata, - /// SDK session ID for the connected remote session. - pub session_id: SessionId, +pub struct QueueRemoveMostRecentResult { + /// True if a user-facing pending item was removed (LIFO across both queues); false when no removable items remained. + pub removed: bool, } -/// Schema for the `ServerSkill` type. +/// Event type to register consumer interest for, used by runtime gating logic. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ServerSkill { - /// Description of what the skill does - pub description: String, - /// Whether the skill is currently enabled (based on global config) - pub enabled: bool, - /// Unique identifier for the skill - pub name: String, - /// Absolute path to the skill file - #[serde(skip_serializing_if = "Option::is_none")] - pub path: Option, - /// The project path this skill belongs to (only for project/inherited skills) - #[serde(skip_serializing_if = "Option::is_none")] - pub project_path: Option, - /// Source location type (e.g., project, personal-copilot, plugin, builtin) - pub source: SkillSource, - /// Whether the skill can be invoked by the user as a slash command - pub user_invocable: bool, +pub struct RegisterEventInterestParams { + /// The event type the consumer wants the runtime to treat as 'observed' for behavior-switching gating. Some runtime code paths inspect whether any consumer is interested in a specific event type and choose a different implementation accordingly (e.g. `mcp.oauth_required`: when interest is registered the runtime delegates the full interactive OAuth flow to the consumer; when no interest is registered the runtime installs a browserless fallback that silently reuses cached tokens). SDK clients that long-poll events do NOT automatically appear as listeners to these gating checks — they must explicitly call `registerInterest` for each event type they want the runtime to count as having a consumer. Multiple registrations for the same event type from the same or different consumers are tracked independently and must each be released. See: `mcp.oauth_required`, `sampling.requested`, `auto_mode_switch.requested`, `user_input.requested`, `elicitation.requested`, `command.queued`, `exit_plan_mode.requested`. + pub event_type: String, } -/// Skills discovered across global and project sources. +/// Opaque handle representing an event-type interest registration. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ServerSkillList { - /// All discovered skills across all sources - pub skills: Vec, +pub struct RegisterEventInterestResult { + /// Opaque handle for this registration. Pass to releaseInterest to release. Each call to registerInterest produces a fresh handle, even when the same eventType is registered multiple times. + pub handle: String, } -/// Authentication status and account metadata for the session. +/// Opaque handle previously returned by `registerInterest` to release. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAuthStatus { - /// Authentication type - #[serde(skip_serializing_if = "Option::is_none")] - pub auth_type: Option, - /// Copilot plan tier (e.g., individual_pro, business) - #[serde(skip_serializing_if = "Option::is_none")] - pub copilot_plan: Option, - /// Authentication host URL - #[serde(skip_serializing_if = "Option::is_none")] - pub host: Option, - /// Whether the session has resolved authentication - pub is_authenticated: bool, - /// Authenticated login/username, if available - #[serde(skip_serializing_if = "Option::is_none")] - pub login: Option, - /// Human-readable authentication status description - #[serde(skip_serializing_if = "Option::is_none")] - pub status_message: Option, +pub struct ReleaseEventInterestParams { + /// Handle returned by a previous `registerInterest` call. Idempotent: releasing an unknown or already-released handle is a no-op (returns success). When the last outstanding handle for an event type is released, the runtime reverts to its 'no consumer' code path for that event type. + pub handle: String, } -/// File path, content to append, and optional mode for the client-provided session filesystem. +/// Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsAppendFileRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, - /// Content to append - pub content: String, - /// Optional POSIX-style mode for newly created files +pub struct RemoteEnableRequest { + /// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. #[serde(skip_serializing_if = "Option::is_none")] - pub mode: Option, + pub mode: Option, } -/// Describes a filesystem error. +/// GitHub URL for the session and a flag indicating whether remote steering is enabled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsError { - /// Error classification - pub code: SessionFsErrorCode, - /// Free-form detail about the error, for logging/diagnostics +pub struct RemoteEnableResult { + /// Whether remote steering is enabled + pub remote_steerable: bool, + /// GitHub frontend URL for this session #[serde(skip_serializing_if = "Option::is_none")] - pub message: Option, + pub url: Option, } -/// Path to test for existence in the client-provided session filesystem. +/// New remote-steerability state to persist as a `session.remote_steerable_changed` event. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsExistsRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, +pub struct RemoteNotifySteerableChangedRequest { + /// Whether the session now supports remote steering via GitHub. The runtime persists this as a `session.remote_steerable_changed` event so resume/replay sees the up-to-date capability. + pub remote_steerable: bool, } -/// Indicates whether the requested path exists in the client-provided session filesystem. +/// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsExistsResult { - /// Whether the path exists - pub exists: bool, -} +pub struct RemoteNotifySteerableChangedResult {} -/// Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. +/// Remote session connection result. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsMkdirRequest { - /// Target session identifier +pub struct RemoteSessionConnectionResult { + /// Metadata for a connected remote session. + pub metadata: ConnectedRemoteSessionMetadata, + /// SDK session ID for the connected remote session. pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, - /// Create parent directories as needed - #[serde(skip_serializing_if = "Option::is_none")] - pub recursive: Option, - /// Optional POSIX-style mode for newly created directories - #[serde(skip_serializing_if = "Option::is_none")] - pub mode: Option, } -/// Directory path whose entries should be listed from the client-provided session filesystem. +/// Schema for the `ScheduleEntry` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReaddirRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, +pub struct ScheduleEntry { + /// Display-only label for the prompt as shown in the UI (e.g. `/skill-name` for a skill-invocation schedule). The actual enqueued prompt is `prompt`. + #[serde(skip_serializing_if = "Option::is_none")] + pub display_prompt: Option, + /// Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt from the event log). + pub id: i64, + /// Interval between scheduled ticks, in milliseconds. + pub interval_ms: i64, + /// ISO 8601 timestamp when the next tick is scheduled to fire. + pub next_run_at: String, + /// Prompt text that gets enqueued on every tick. + pub prompt: String, + /// Whether the schedule re-arms after each tick (`/every`) or fires once (`/after`). + pub recurring: bool, } -/// Names of entries in the requested directory, or a filesystem error if the read failed. +/// Snapshot of the currently active recurring prompts for this session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReaddirResult { - /// Entry names in the directory - pub entries: Vec, - /// Describes a filesystem error. - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, +pub struct ScheduleList { + /// Active scheduled prompts, ordered by id. + pub entries: Vec, } -/// Schema for the `SessionFsReaddirWithTypesEntry` type. +/// Identifier of the scheduled prompt to remove. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReaddirWithTypesEntry { - /// Entry name - pub name: String, - /// Entry type - pub r#type: SessionFsReaddirWithTypesEntryType, +pub struct ScheduleStopRequest { + /// Id of the scheduled prompt to remove. + pub id: i64, } -/// Directory path whose entries (with type information) should be listed from the client-provided session filesystem. +/// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReaddirWithTypesRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, +pub struct ScheduleStopResult { + /// The removed entry, or omitted if no entry matched. + #[serde(skip_serializing_if = "Option::is_none")] + pub entry: Option, } -/// Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. +/// Blob attachment with inline base64-encoded data #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReaddirWithTypesResult { - /// Directory entries with type information - pub entries: Vec, - /// Describes a filesystem error. +pub struct SendAttachmentBlob { + /// Base64-encoded content + pub data: String, + /// User-facing display name for the attachment #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, + pub display_name: Option, + /// MIME type of the inline data + pub mime_type: String, + /// Attachment type discriminator + pub r#type: SendAttachmentBlobType, } -/// Path of the file to read from the client-provided session filesystem. +/// Directory attachment #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReadFileRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions +pub struct SendAttachmentDirectory { + /// User-facing display name for the attachment + pub display_name: String, + /// Absolute directory path pub path: String, + /// Attachment type discriminator + pub r#type: SendAttachmentDirectoryType, } -/// File content as a UTF-8 string, or a filesystem error if the read failed. +/// Optional line range to scope the attachment to a specific section of the file #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsReadFileResult { - /// File content as UTF-8 string - pub content: String, - /// Describes a filesystem error. - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, +pub struct SendAttachmentFileLineRange { + /// End line number (1-based, inclusive) + pub end: i64, + /// Start line number (1-based) + pub start: i64, } -/// Source and destination paths for renaming or moving an entry in the client-provided session filesystem. +/// File attachment #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsRenameRequest { - /// Target session identifier - pub session_id: SessionId, - /// Source path using SessionFs conventions - pub src: String, - /// Destination path using SessionFs conventions - pub dest: String, +pub struct SendAttachmentFile { + /// User-facing display name for the attachment + pub display_name: String, + /// Optional line range to scope the attachment to a specific section of the file + #[serde(skip_serializing_if = "Option::is_none")] + pub line_range: Option, + /// Absolute file path + pub path: String, + /// Attachment type discriminator + pub r#type: SendAttachmentFileType, } -/// Path to remove from the client-provided session filesystem, with options for recursive removal and force. +/// GitHub issue, pull request, or discussion reference #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsRmRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, - /// Remove directories and their contents recursively - #[serde(skip_serializing_if = "Option::is_none")] - pub recursive: Option, - /// Ignore errors if the path does not exist - #[serde(skip_serializing_if = "Option::is_none")] - pub force: Option, +pub struct SendAttachmentGithubReference { + /// Issue, pull request, or discussion number + pub number: i64, + /// Type of GitHub reference + pub reference_type: SendAttachmentGithubReferenceType, + /// Current state of the referenced item (e.g., open, closed, merged) + pub state: String, + /// Title of the referenced item + pub title: String, + /// Attachment type discriminator + pub r#type: SendAttachmentGithubReferenceType, + /// URL to the referenced item on GitHub + pub url: String, } -/// Optional capabilities declared by the provider +/// End position of the selection #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSetProviderCapabilities { - /// Whether the provider supports SQLite query/exists operations - #[serde(skip_serializing_if = "Option::is_none")] - pub sqlite: Option, +pub struct SendAttachmentSelectionDetailsEnd { + /// End character offset within the line (0-based) + pub character: i64, + /// End line number (0-based) + pub line: i64, } -/// Initial working directory, session-state path layout, and path conventions used to register the calling SDK client as the session filesystem provider. +/// Start position of the selection #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSetProviderRequest { - /// Optional capabilities declared by the provider - #[serde(skip_serializing_if = "Option::is_none")] - pub capabilities: Option, - /// Path conventions used by this filesystem - pub conventions: SessionFsSetProviderConventions, - /// Initial working directory for sessions - pub initial_cwd: String, - /// Path within each session's SessionFs where the runtime stores files for that session - pub session_state_path: String, +pub struct SendAttachmentSelectionDetailsStart { + /// Start character offset within the line (0-based) + pub character: i64, + /// Start line number (0-based) + pub line: i64, } -/// Indicates whether the calling client was registered as the session filesystem provider. +/// Position range of the selection within the file #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSetProviderResult { - /// Whether the provider was set successfully - pub success: bool, +pub struct SendAttachmentSelectionDetails { + /// End position of the selection + pub end: SendAttachmentSelectionDetailsEnd, + /// Start position of the selection + pub start: SendAttachmentSelectionDetailsStart, } -/// Indicates whether the per-session SQLite database already exists. +/// Code selection attachment from an editor #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSqliteExistsResult { - /// Whether the session database already exists - pub exists: bool, +pub struct SendAttachmentSelection { + /// User-facing display name for the selection + pub display_name: String, + /// Absolute path to the file containing the selection + pub file_path: String, + /// Position range of the selection within the file + pub selection: SendAttachmentSelectionDetails, + /// The selected text content + pub text: String, + /// Attachment type discriminator + pub r#type: SendAttachmentSelectionType, } -/// SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. +/// Parameters for sending a user message to the session #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSqliteQueryRequest { - /// Target session identifier - pub session_id: SessionId, - /// SQL query to execute - pub query: String, - /// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) - pub query_type: SessionFsSqliteQueryType, - /// Optional named bind parameters +pub struct SendRequest { + /// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. + #[serde(skip_serializing_if = "Option::is_none")] + pub agent_mode: Option, + /// Optional attachments (files, directories, selections, blobs, GitHub references) to include with the message #[serde(default)] - pub params: HashMap, + pub attachments: Vec, + /// If false, this message will not trigger a Premium Request Unit charge. User messages default to billable. + #[serde(skip_serializing_if = "Option::is_none")] + pub billable: Option, + /// If provided, this is shown in the timeline instead of `prompt` + #[serde(skip_serializing_if = "Option::is_none")] + pub display_prompt: Option, + /// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. + #[serde(skip_serializing_if = "Option::is_none")] + pub mode: Option, + /// If true, adds the message to the front of the queue instead of the end + #[serde(skip_serializing_if = "Option::is_none")] + pub prepend: Option, + /// The user message text + pub prompt: String, + /// Custom HTTP headers to include in outbound model requests for this turn. Merged with session-level provider headers; per-turn headers augment and overwrite session-level headers with the same key. + #[serde(default)] + pub request_headers: HashMap, + /// If set, the request will fail if the named tool is not available when this message is among the user messages at the start of the current exchange + #[serde(skip_serializing_if = "Option::is_none")] + pub required_tool: Option, + /// Optional provenance tag copied to the resulting user.message event. Supported values are `system`, `command-*`, and `schedule-*`. + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option, + /// W3C Trace Context traceparent header for distributed tracing of this agent turn + #[serde(skip_serializing_if = "Option::is_none")] + pub traceparent: Option, + /// W3C Trace Context tracestate header for distributed tracing + #[serde(skip_serializing_if = "Option::is_none")] + pub tracestate: Option, + /// If true, await completion of the agentic loop for this message before returning. Defaults to false (fire-and-forget). When true, the result still contains the same `messageId`; the caller can rely on the agent having processed the message before the call resolves. + #[serde(skip_serializing_if = "Option::is_none")] + pub wait: Option, } -/// Query results including rows, columns, and rows affected, or a filesystem error if execution failed. +/// Result of sending a user message #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsSqliteQueryResult { - /// Column names from the result set - pub columns: Vec, - /// Describes a filesystem error. - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - /// Last inserted row ID (for INSERT) - #[serde(skip_serializing_if = "Option::is_none")] - pub last_insert_rowid: Option, - /// For SELECT: array of row objects. For others: empty array. - pub rows: Vec>, - /// Number of rows affected (for INSERT/UPDATE/DELETE) - pub rows_affected: i64, +pub struct SendResult { + /// Unique identifier assigned to the message + pub message_id: String, } -/// Path whose metadata should be returned from the client-provided session filesystem. +/// Schema for the `ServerSkill` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsStatRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, +pub struct ServerSkill { + /// Description of what the skill does + pub description: String, + /// Whether the skill is currently enabled (based on global config) + pub enabled: bool, + /// Unique identifier for the skill + pub name: String, + /// Absolute path to the skill file + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + /// The project path this skill belongs to (only for project/inherited skills) + #[serde(skip_serializing_if = "Option::is_none")] + pub project_path: Option, + /// Source location type (e.g., project, personal-copilot, plugin, builtin) + pub source: SkillSource, + /// Whether the skill can be invoked by the user as a slash command + pub user_invocable: bool, } -/// Filesystem metadata for the requested path, or a filesystem error if the stat failed. +/// Skills discovered across global and project sources. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsStatResult { - /// ISO 8601 timestamp of creation - pub birthtime: String, - /// Describes a filesystem error. - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - /// Whether the path is a directory - pub is_directory: bool, - /// Whether the path is a file - pub is_file: bool, - /// ISO 8601 timestamp of last modification - pub mtime: String, - /// File size in bytes - pub size: i64, +pub struct ServerSkillList { + /// All discovered skills across all sources + pub skills: Vec, } -/// File path, content to write, and optional mode for the client-provided session filesystem. +/// Authentication status and account metadata for the session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFsWriteFileRequest { - /// Target session identifier - pub session_id: SessionId, - /// Path using SessionFs conventions - pub path: String, - /// Content to write - pub content: String, - /// Optional POSIX-style mode for newly created files +pub struct SessionAuthStatus { + /// Authentication type #[serde(skip_serializing_if = "Option::is_none")] - pub mode: Option, + pub auth_type: Option, + /// Copilot plan tier (e.g., individual_pro, business) + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_plan: Option, + /// Authentication host URL + #[serde(skip_serializing_if = "Option::is_none")] + pub host: Option, + /// Whether the session has resolved authentication + pub is_authenticated: bool, + /// Authenticated login/username, if available + #[serde(skip_serializing_if = "Option::is_none")] + pub login: Option, + /// Human-readable authentication status description + #[serde(skip_serializing_if = "Option::is_none")] + pub status_message: Option, } -/// Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. +/// Map of sessionId -> bytes freed by removing the session's workspace directory. /// ///
/// @@ -2255,18 +3924,12 @@ pub struct SessionFsWriteFileRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionsForkRequest { - /// Optional friendly name to assign to the forked session. - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, - /// Source session ID to fork from - pub session_id: SessionId, - /// Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. - #[serde(skip_serializing_if = "Option::is_none")] - pub to_event_id: Option, +pub struct SessionBulkDeleteResult { + /// Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions whose deletion failed are omitted from this map (failures are logged on the server but not surfaced per-id; check the map for absent IDs to detect them). + pub freed_bytes: HashMap, } -/// Identifier and optional friendly name assigned to the newly forked session. +/// Schema for the `SessionContext` type. /// ///
/// @@ -2276,56 +3939,24 @@ pub struct SessionsForkRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionsForkResult { - /// Friendly name assigned to the forked session, if any. +pub struct SessionContext { + /// Active git branch #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, - /// The new forked session's ID - pub session_id: SessionId, -} - -/// Shell command to run, with optional working directory and timeout in milliseconds. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShellExecRequest { - /// Shell command to execute - pub command: String, - /// Working directory (defaults to session working directory) + pub branch: Option, + /// Most recent working directory for this session + pub cwd: String, + /// Git repository root, if the cwd was inside a git repo #[serde(skip_serializing_if = "Option::is_none")] - pub cwd: Option, - /// Timeout in milliseconds (default: 30000) + pub git_root: Option, + /// Repository host type #[serde(skip_serializing_if = "Option::is_none")] - pub timeout: Option, -} - -/// Identifier of the spawned process, used to correlate streamed output and exit notifications. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShellExecResult { - /// Unique identifier for tracking streamed output - pub process_id: String, -} - -/// Identifier of a process previously returned by "shell.exec" and the signal to send. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShellKillRequest { - /// Process identifier returned by shell.exec - pub process_id: String, - /// Signal to send (default: SIGTERM) + pub host_type: Option, + /// Repository slug in `owner/name` form, when known #[serde(skip_serializing_if = "Option::is_none")] - pub signal: Option, -} - -/// Indicates whether the signal was delivered; false if the process was unknown or already exited. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShellKillResult { - /// Whether the signal was sent successfully - pub killed: bool, + pub repository: Option, } -/// Schema for the `Skill` type. +/// Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). /// ///
/// @@ -2335,23 +3966,28 @@ pub struct ShellKillResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct Skill { - /// Description of what the skill does - pub description: String, - /// Whether the skill is currently enabled - pub enabled: bool, - /// Unique identifier for the skill - pub name: String, - /// Absolute path to the skill file - #[serde(skip_serializing_if = "Option::is_none")] - pub path: Option, - /// Source location type (e.g., project, personal-copilot, plugin, builtin) - pub source: SkillSource, - /// Whether the skill can be invoked by the user as a slash command - pub user_invocable: bool, -} - -/// Skills available to the session, with their enabled state. +pub struct SessionContextInfo { + /// Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%) + pub buffer_tokens: i64, + /// Token count at which background compaction starts (configurable percentage of promptTokenLimit) + pub compaction_threshold: i64, + /// Tokens consumed by user/assistant/tool messages + pub conversation_tokens: i64, + /// Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. + pub limit: i64, + /// The model used for token counting + pub model_name: String, + /// Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified) + pub prompt_token_limit: i64, + /// Tokens consumed by the system prompt + pub system_tokens: i64, + /// Tokens consumed by tool definitions sent to the model (excludes deferred tools) + pub tool_definitions_tokens: i64, + /// Sum of system, conversation and tool-definition tokens + pub total_tokens: i64, +} + +/// Schema for the `SessionMetadata` type. /// ///
/// @@ -2361,20 +3997,30 @@ pub struct Skill { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillList { - /// Available skills - pub skills: Vec, -} - -/// Skill names to mark as disabled in global configuration, replacing any previous list. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SkillsConfigSetDisabledSkillsRequest { - /// List of skill names to disable - pub disabled_skills: Vec, +pub struct SessionMetadata { + /// Schema for the `SessionContext` type. + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option, + /// True for remote (GitHub) sessions; false for local + pub is_remote: bool, + /// GitHub task ID, when this local session is bound to one. Only present for local sessions exported to remote control. + #[serde(skip_serializing_if = "Option::is_none")] + pub mc_task_id: Option, + /// Last-modified time of the session's persisted state, as ISO 8601 + pub modified_time: String, + /// Optional human-friendly name set via /rename + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// Stable session identifier + pub session_id: SessionId, + /// Session creation time as an ISO 8601 timestamp + pub start_time: String, + /// Short summary of the session, when one has been derived + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, } -/// Name of the skill to disable for the session. +/// The same metadata records, with summary and context fields backfilled where available. /// ///
/// @@ -2384,283 +4030,290 @@ pub struct SkillsConfigSetDisabledSkillsRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillsDisableRequest { - /// Name of the skill to disable - pub name: String, +pub struct SessionEnrichMetadataResult { + /// Same records, with summary and context backfilled + pub sessions: Vec, } -/// Optional project paths and additional skill directories to include in discovery. +/// File path, content to append, and optional mode for the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillsDiscoverRequest { - /// Optional list of project directory paths to scan for project-scoped skills - #[serde(default)] - pub project_paths: Vec, - /// Optional list of additional skill directory paths to include - #[serde(default)] - pub skill_directories: Vec, +pub struct SessionFsAppendFileRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, + /// Content to append + pub content: String, + /// Optional POSIX-style mode for newly created files + #[serde(skip_serializing_if = "Option::is_none")] + pub mode: Option, } -/// Name of the skill to enable for the session. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Describes a filesystem error. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillsEnableRequest { - /// Name of the skill to enable - pub name: String, +pub struct SessionFsError { + /// Error classification + pub code: SessionFsErrorCode, + /// Free-form detail about the error, for logging/diagnostics + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, } -/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Path to test for existence in the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillsLoadDiagnostics { - /// Errors emitted while loading skills (e.g. skills that failed to load entirely) - pub errors: Vec, - /// Warnings emitted while loading skills (e.g. skills that loaded but had issues) - pub warnings: Vec, +pub struct SessionFsExistsRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, } -/// Schema for the `SlashCommandAgentPromptResult` type. +/// Indicates whether the requested path exists in the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SlashCommandAgentPromptResult { - /// Prompt text to display to the user - pub display_prompt: String, - /// Agent prompt result discriminator - pub kind: SlashCommandAgentPromptResultKind, - /// Optional target session mode for the agent prompt - #[serde(skip_serializing_if = "Option::is_none")] - pub mode: Option, - /// Prompt to submit to the agent - pub prompt: String, - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh - #[serde(skip_serializing_if = "Option::is_none")] - pub runtime_settings_changed: Option, +pub struct SessionFsExistsResult { + /// Whether the path exists + pub exists: bool, } -/// Schema for the `SlashCommandCompletedResult` type. +/// Directory path to create in the client-provided session filesystem, with options for recursive creation and POSIX mode. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SlashCommandCompletedResult { - /// Completed result discriminator - pub kind: SlashCommandCompletedResultKind, - /// Optional user-facing message describing the completed command +pub struct SessionFsMkdirRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, + /// Create parent directories as needed #[serde(skip_serializing_if = "Option::is_none")] - pub message: Option, - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh + pub recursive: Option, + /// Optional POSIX-style mode for newly created directories #[serde(skip_serializing_if = "Option::is_none")] - pub runtime_settings_changed: Option, + pub mode: Option, } -/// Schema for the `SlashCommandTextResult` type. +/// Directory path whose entries should be listed from the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SlashCommandTextResult { - /// Text result discriminator - pub kind: SlashCommandTextResultKind, - /// Whether text contains Markdown - #[serde(skip_serializing_if = "Option::is_none")] - pub markdown: Option, - /// Whether ANSI sequences should be preserved - #[serde(skip_serializing_if = "Option::is_none")] - pub preserve_ansi: Option, - /// True when the invocation mutated user runtime settings; consumers caching settings should refresh - #[serde(skip_serializing_if = "Option::is_none")] - pub runtime_settings_changed: Option, - /// Text output for the client to render - pub text: String, +pub struct SessionFsReaddirRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, } -/// Schema for the `TaskAgentInfo` type. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Names of entries in the requested directory, or a filesystem error if the read failed. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TaskAgentInfo { - /// ISO 8601 timestamp when the current active period began - #[serde(skip_serializing_if = "Option::is_none")] - pub active_started_at: Option, - /// Accumulated active execution time in milliseconds - #[serde(skip_serializing_if = "Option::is_none")] - pub active_time_ms: Option, - /// Type of agent running this task - pub agent_type: String, - /// Whether the task is currently in the original sync wait and can be moved to background mode. False once it is already backgrounded, idle, finished, or no longer has a promotable sync waiter. - #[serde(skip_serializing_if = "Option::is_none")] - pub can_promote_to_background: Option, - /// ISO 8601 timestamp when the task finished - #[serde(skip_serializing_if = "Option::is_none")] - pub completed_at: Option, - /// Short description of the task - pub description: String, - /// Error message when the task failed - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - /// Whether task execution is synchronously awaited or managed in the background - #[serde(skip_serializing_if = "Option::is_none")] - pub execution_mode: Option, - /// Unique task identifier - pub id: String, - /// ISO 8601 timestamp when the agent entered idle state - #[serde(skip_serializing_if = "Option::is_none")] - pub idle_since: Option, - /// Most recent response text from the agent - #[serde(skip_serializing_if = "Option::is_none")] - pub latest_response: Option, - /// Model used for the task when specified - #[serde(skip_serializing_if = "Option::is_none")] - pub model: Option, - /// Prompt passed to the agent - pub prompt: String, - /// Result text from the task when available +pub struct SessionFsReaddirResult { + /// Entry names in the directory + pub entries: Vec, + /// Describes a filesystem error. #[serde(skip_serializing_if = "Option::is_none")] - pub result: Option, - /// ISO 8601 timestamp when the task was started - pub started_at: String, - /// Current lifecycle status of the task - pub status: TaskStatus, - /// Tool call ID associated with this agent task - pub tool_call_id: String, - /// Task kind - pub r#type: TaskAgentInfoType, + pub error: Option, } -/// Background tasks currently tracked by the session. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Schema for the `SessionFsReaddirWithTypesEntry` type. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TaskList { - /// Currently tracked tasks - pub tasks: Vec, +pub struct SessionFsReaddirWithTypesEntry { + /// Entry name + pub name: String, + /// Entry type + pub r#type: SessionFsReaddirWithTypesEntryType, } -/// Identifier of the background task to cancel. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Directory path whose entries (with type information) should be listed from the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksCancelRequest { - /// Task identifier - pub id: String, +pub struct SessionFsReaddirWithTypesRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, } -/// Indicates whether the background task was successfully cancelled. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksCancelResult { - /// Whether the task was successfully cancelled - pub cancelled: bool, +pub struct SessionFsReaddirWithTypesResult { + /// Directory entries with type information + pub entries: Vec, + /// Describes a filesystem error. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, } -/// Schema for the `TaskShellInfo` type. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Path of the file to read from the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TaskShellInfo { - /// Whether the shell runs inside a managed PTY session or as an independent background process - pub attachment_mode: TaskShellInfoAttachmentMode, - /// Whether this shell task can be promoted to background mode - #[serde(skip_serializing_if = "Option::is_none")] - pub can_promote_to_background: Option, - /// Command being executed - pub command: String, - /// ISO 8601 timestamp when the task finished - #[serde(skip_serializing_if = "Option::is_none")] - pub completed_at: Option, - /// Short description of the task - pub description: String, - /// Whether task execution is synchronously awaited or managed in the background - #[serde(skip_serializing_if = "Option::is_none")] - pub execution_mode: Option, - /// Unique task identifier - pub id: String, - /// Path to the detached shell log, when available - #[serde(skip_serializing_if = "Option::is_none")] - pub log_path: Option, - /// Process ID when available - #[serde(skip_serializing_if = "Option::is_none")] - pub pid: Option, - /// ISO 8601 timestamp when the task was started - pub started_at: String, - /// Current lifecycle status of the task - pub status: TaskStatus, - /// Task kind - pub r#type: TaskShellInfoType, +pub struct SessionFsReadFileRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, } -/// Identifier of the task to promote to background mode. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// File content as a UTF-8 string, or a filesystem error if the read failed. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksPromoteToBackgroundRequest { - /// Task identifier - pub id: String, +pub struct SessionFsReadFileResult { + /// File content as UTF-8 string + pub content: String, + /// Describes a filesystem error. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, } -/// Indicates whether the task was successfully promoted to background mode. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Source and destination paths for renaming or moving an entry in the client-provided session filesystem. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksPromoteToBackgroundResult { - /// Whether the task was successfully promoted to background mode - pub promoted: bool, +pub struct SessionFsRenameRequest { + /// Target session identifier + pub session_id: SessionId, + /// Source path using SessionFs conventions + pub src: String, + /// Destination path using SessionFs conventions + pub dest: String, } -/// Identifier of the completed or cancelled task to remove from tracking. +/// Path to remove from the client-provided session filesystem, with options for recursive removal and force. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsRmRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, + /// Remove directories and their contents recursively + #[serde(skip_serializing_if = "Option::is_none")] + pub recursive: Option, + /// Ignore errors if the path does not exist + #[serde(skip_serializing_if = "Option::is_none")] + pub force: Option, +} + +/// Optional capabilities declared by the provider +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSetProviderCapabilities { + /// Whether the provider supports SQLite query/exists operations + #[serde(skip_serializing_if = "Option::is_none")] + pub sqlite: Option, +} + +/// Initial working directory, session-state path layout, and path conventions used to register the calling SDK client as the session filesystem provider. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSetProviderRequest { + /// Optional capabilities declared by the provider + #[serde(skip_serializing_if = "Option::is_none")] + pub capabilities: Option, + /// Path conventions used by this filesystem + pub conventions: SessionFsSetProviderConventions, + /// Initial working directory for sessions + pub initial_cwd: String, + /// Path within each session's SessionFs where the runtime stores files for that session + pub session_state_path: String, +} + +/// Indicates whether the calling client was registered as the session filesystem provider. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSetProviderResult { + /// Whether the provider was set successfully + pub success: bool, +} + +/// Indicates whether the per-session SQLite database already exists. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSqliteExistsResult { + /// Whether the session database already exists + pub exists: bool, +} + +/// SQL query, query type, and optional bind parameters for executing a SQLite query against the per-session database. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSqliteQueryRequest { + /// Target session identifier + pub session_id: SessionId, + /// SQL query to execute + pub query: String, + /// How to execute the query: 'exec' for DDL/multi-statement (no results), 'query' for SELECT (returns rows), 'run' for INSERT/UPDATE/DELETE (returns rowsAffected) + pub query_type: SessionFsSqliteQueryType, + /// Optional named bind parameters + #[serde(default)] + pub params: HashMap, +} + +/// Query results including rows, columns, and rows affected, or a filesystem error if execution failed. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsSqliteQueryResult { + /// Column names from the result set + pub columns: Vec, + /// Describes a filesystem error. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// SQLite last_insert_rowid() value for INSERT. + #[serde(skip_serializing_if = "Option::is_none")] + pub last_insert_rowid: Option, + /// For SELECT: array of row objects. For others: empty array. + pub rows: Vec>, + /// Number of rows affected (for INSERT/UPDATE/DELETE) + pub rows_affected: i64, +} + +/// Path whose metadata should be returned from the client-provided session filesystem. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsStatRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, +} + +/// Filesystem metadata for the requested path, or a filesystem error if the stat failed. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsStatResult { + /// ISO 8601 timestamp of creation + pub birthtime: String, + /// Describes a filesystem error. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether the path is a directory + pub is_directory: bool, + /// Whether the path is a file + pub is_file: bool, + /// ISO 8601 timestamp of last modification + pub mtime: String, + /// File size in bytes + pub size: i64, +} + +/// File path, content to write, and optional mode for the client-provided session filesystem. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFsWriteFileRequest { + /// Target session identifier + pub session_id: SessionId, + /// Path using SessionFs conventions + pub path: String, + /// Content to write + pub content: String, + /// Optional POSIX-style mode for newly created files + #[serde(skip_serializing_if = "Option::is_none")] + pub mode: Option, +} + +/// Schema for the `SessionInstalledPlugin` type. /// ///
/// @@ -2670,12 +4323,28 @@ pub struct TasksPromoteToBackgroundResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksRemoveRequest { - /// Task identifier - pub id: String, +pub struct SessionInstalledPlugin { + /// Path where the plugin is cached locally + #[serde(rename = "cache_path", skip_serializing_if = "Option::is_none")] + pub cache_path: Option, + /// Whether the plugin is currently enabled + pub enabled: bool, + /// Installation timestamp (ISO-8601) + #[serde(rename = "installed_at")] + pub installed_at: String, + /// Marketplace the plugin came from (empty string for direct repo installs) + pub marketplace: String, + /// Plugin name + pub name: String, + /// Source descriptor for direct repo installs (when marketplace is empty) + #[serde(skip_serializing_if = "Option::is_none")] + pub source: Option, + /// Installed version, if known + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, } -/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. +/// Schema for the `SessionInstalledPluginSourceGithub` type. /// ///
/// @@ -2685,12 +4354,17 @@ pub struct TasksRemoveRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksRemoveResult { - /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). - pub removed: bool, +pub struct SessionInstalledPluginSourceGithub { + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + pub repo: String, + /// Constant value. Always "github". + pub source: SessionInstalledPluginSourceGithubSource, } -/// Identifier of the target agent task, message content, and optional sender agent ID. +/// Schema for the `SessionInstalledPluginSourceLocal` type. /// ///
/// @@ -2700,17 +4374,13 @@ pub struct TasksRemoveResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksSendMessageRequest { - /// Agent ID of the sender, if sent on behalf of another agent - #[serde(skip_serializing_if = "Option::is_none")] - pub from_agent_id: Option, - /// Agent task identifier - pub id: String, - /// Message content to send to the agent - pub message: String, +pub struct SessionInstalledPluginSourceLocal { + pub path: String, + /// Constant value. Always "local". + pub source: SessionInstalledPluginSourceLocalSource, } -/// Indicates whether the message was delivered, with an error message when delivery failed. +/// Schema for the `SessionInstalledPluginSourceUrl` type. /// ///
/// @@ -2720,15 +4390,17 @@ pub struct TasksSendMessageRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksSendMessageResult { - /// Error message if delivery failed +pub struct SessionInstalledPluginSourceUrl { #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - /// Whether the message was successfully delivered or steered - pub sent: bool, + pub path: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub r#ref: Option, + /// Constant value. Always "url". + pub source: SessionInstalledPluginSourceUrlSource, + pub url: String, } -/// Agent type, prompt, name, and optional description and model override for the new task. +/// Persisted sessions matching the filter, ordered most-recently-modified first. /// ///
/// @@ -2738,22 +4410,12 @@ pub struct TasksSendMessageResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksStartAgentRequest { - /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose') - pub agent_type: String, - /// Short description of the task - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Optional model override - #[serde(skip_serializing_if = "Option::is_none")] - pub model: Option, - /// Short name for the agent, used to generate a human-readable ID - pub name: String, - /// Task prompt for the agent - pub prompt: String, +pub struct SessionList { + /// Sessions ordered most-recently-modified first + pub sessions: Vec, } -/// Identifier assigned to the newly started background agent task. +/// Queued repo-level startup prompts and the total hook command count after loading. /// ///
/// @@ -2763,295 +4425,3165 @@ pub struct TasksStartAgentRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct TasksStartAgentResult { - /// Generated agent ID for the background task - pub agent_id: String, +pub struct SessionLoadDeferredRepoHooksResult { + /// Total hook command count (user + plugin + repo) loaded for the session by this call. Captured atomically with startupPrompts so callers don't need to read a separate counter. + pub hook_count: i64, + /// Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo configs were pending, or when disableAllHooks is set. + pub startup_prompts: Vec, } -/// Schema for the `Tool` type. +/// Public-facing projection of workspace metadata for SDK / TUI consumers #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct Tool { - /// Description of what the tool does - pub description: String, - /// Optional instructions for how to use this tool effectively +pub struct SessionMetadataSnapshotWorkspace { + /// Branch checked out at session start, if any #[serde(skip_serializing_if = "Option::is_none")] - pub instructions: Option, - /// Tool identifier (e.g., "bash", "grep", "str_replace_editor") - pub name: String, - /// Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP tools) + pub branch: Option, + /// ISO 8601 timestamp when the workspace was created + #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] + pub created_at: Option, + /// Current working directory at session start #[serde(skip_serializing_if = "Option::is_none")] - pub namespaced_name: Option, - /// JSON Schema for the tool's input parameters - #[serde(default)] - pub parameters: HashMap, + pub cwd: Option, + /// Resolved git root for cwd, if any + #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Repository host type, if known + #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] + pub host_type: Option, + /// Workspace identifier (1:1 with sessionId) + pub id: String, + /// Display name for the session, if set + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// Repository identifier in 'owner/repo' or 'org/project/repo' format, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + /// ISO 8601 timestamp when the workspace was last updated + #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] + pub updated_at: Option, } -/// Built-in tools available for the requested model, with their parameters and instructions. +/// Point-in-time snapshot of slow-changing session identifier and state fields +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ToolList { - /// List of available built-in tools with metadata - pub tools: Vec, +pub struct SessionMetadataSnapshot { + /// True when the session was detected to be in use by another process at construction time. Local consumers may surface a confirmation prompt before fully attaching. Always false for new sessions. + pub already_in_use: bool, + /// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') + pub current_mode: MetadataSnapshotCurrentMode, + /// User-provided name supplied at session construction (via `--name`), if any. Immutable after construction. + #[serde(skip_serializing_if = "Option::is_none")] + pub initial_name: Option, + /// Whether this is a remote session (i.e., one whose runtime executes elsewhere and is steered through this process) + pub is_remote: bool, + /// ISO 8601 timestamp of when the session's persisted state was last modified on disk. For new sessions, equals startTime. For resumed sessions, reflects the previous modification time at construction. + pub modified_time: String, + /// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. + #[serde(skip_serializing_if = "Option::is_none")] + pub remote_metadata: Option, + /// Currently selected model identifier, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub selected_model: Option, + /// The unique identifier of the session + pub session_id: SessionId, + /// ISO 8601 timestamp of when the session started + pub start_time: String, + /// Short human-readable summary of the session, if known. Omitted when no summary has been generated. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, + /// Absolute path to the session's current working directory + pub working_directory: String, + /// Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). + pub workspace: Option, + /// Absolute path to the session's workspace directory on disk, or null if the session has no associated workspace + pub workspace_path: Option, } -/// Optional model identifier whose tool overrides should be applied to the listing. +/// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ToolsListRequest { - /// Optional model ID — when provided, the returned tool list reflects model-specific overrides - #[serde(skip_serializing_if = "Option::is_none")] - pub model: Option, +pub struct SessionPruneResult { + /// Session IDs that would be deleted in dry-run mode (always empty otherwise) + pub candidates: Vec, + /// Session IDs that were deleted (always empty in dry-run mode) + pub deleted: Vec, + /// True when no deletions were actually performed + pub dry_run: bool, + /// Total bytes freed (actual when not dry-run, projected when dry-run) + pub freed_bytes: i64, + /// Session IDs that were skipped (e.g., named sessions) + pub skipped: Vec, } -/// Schema for the `UIElicitationArrayAnyOfFieldItemsAnyOf` type. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct UIElicitationArrayAnyOfFieldItemsAnyOf { - /// Value submitted when this option is selected. - pub r#const: String, - /// Display label for this option. - pub title: String, +/// Session IDs to close, deactivate, and delete from disk. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsBulkDeleteRequest { + /// Session IDs to close, deactivate, and delete from disk + pub session_ids: Vec, } -/// Schema applied to each item in the array. +/// Session IDs to test for live in-use locks. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationArrayAnyOfFieldItems { - /// Selectable options, each with a value and a display label. - pub any_of: Vec, +pub struct SessionsCheckInUseRequest { + /// Session IDs to test for live in-use locks + pub session_ids: Vec, } -/// Multi-select string field where each option pairs a value with a display label. +/// Session IDs from the input set that are currently in use by another process. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationArrayAnyOfField { - /// Default values selected when the form is first shown. - #[serde(default)] - pub default: Vec, - /// Help text describing the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Schema applied to each item in the array. - pub items: UIElicitationArrayAnyOfFieldItems, - /// Maximum number of items the user may select. - #[serde(skip_serializing_if = "Option::is_none")] - pub max_items: Option, - /// Minimum number of items the user must select. - #[serde(skip_serializing_if = "Option::is_none")] - pub min_items: Option, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "array". - pub r#type: UIElicitationArrayAnyOfFieldType, +pub struct SessionsCheckInUseResult { + /// Session IDs from the input set that are currently held by another running process via an alive lock file + pub in_use: Vec, } -/// Schema applied to each item in the array. +/// Session ID to close. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationArrayEnumFieldItems { - /// Allowed string values for each selected item. - pub r#enum: Vec, - /// Type discriminator. Always "string". - pub r#type: UIElicitationArrayEnumFieldItemsType, +pub struct SessionsCloseRequest { + /// Session ID to close + pub session_id: SessionId, } -/// Multi-select string field whose allowed values are defined inline. +/// Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationArrayEnumField { - /// Default values selected when the form is first shown. - #[serde(default)] - pub default: Vec, - /// Help text describing the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Schema applied to each item in the array. - pub items: UIElicitationArrayEnumFieldItems, - /// Maximum number of items the user may select. - #[serde(skip_serializing_if = "Option::is_none")] - pub max_items: Option, - /// Minimum number of items the user must select. - #[serde(skip_serializing_if = "Option::is_none")] - pub min_items: Option, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "array". - pub r#type: UIElicitationArrayEnumFieldType, -} +pub struct SessionsCloseResult {} -/// JSON Schema describing the form fields to present to the user +/// Session metadata records to enrich with summary and context information. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationSchema { - /// Form field definitions, keyed by field name - pub properties: HashMap, - /// List of required field names - #[serde(default)] - pub required: Vec, - /// Schema type indicator (always 'object') - pub r#type: UIElicitationSchemaType, +pub struct SessionsEnrichMetadataRequest { + /// Session metadata records to enrich. Records that already have summary and context are returned unchanged. + pub sessions: Vec, } -/// Prompt message and JSON schema describing the form fields to elicit from the user. +/// New auth credentials to install on the session. Omit to leave credentials unchanged. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationRequest { - /// Message describing what information is needed from the user - pub message: String, - /// JSON Schema describing the form fields to present to the user - pub requested_schema: UIElicitationSchema, +pub struct SessionSetCredentialsParams { + /// The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit. + #[serde(skip_serializing_if = "Option::is_none")] + pub credentials: Option, } -/// The elicitation response (accept with form values, decline, or cancel) +/// Indicates whether the credential update succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationResponse { - /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - pub action: UIElicitationResponseAction, - /// The form values submitted by the user (present when action is 'accept') - #[serde(default)] - pub content: HashMap, +pub struct SessionSetCredentialsResult { + /// Whether the operation succeeded + pub success: bool, } -/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. +/// UUID prefix to resolve to a unique session ID. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationResult { - /// Whether the response was accepted. False if the request was already resolved by another client. - pub success: bool, +pub struct SessionsFindByPrefixRequest { + /// UUID prefix (>=7 hex chars, <36 chars). Returns the unique session ID, or undefined when there is no match or the prefix matches multiple sessions. + pub prefix: String, } -/// Boolean field rendered as a yes/no toggle. +/// Session ID matching the prefix, omitted when no unique match exists. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationSchemaPropertyBoolean { - /// Default value selected when the form is first shown. +pub struct SessionsFindByPrefixResult { + /// Omitted when no unique session matches the prefix (no match or ambiguous) #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - /// Help text describing the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "boolean". - pub r#type: UIElicitationSchemaPropertyBooleanType, + pub session_id: Option, } -/// Numeric field accepting either a number or an integer. +/// GitHub task ID to look up. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationSchemaPropertyNumber { - /// Default value populated in the input when the form is first shown. - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - /// Help text describing the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Maximum allowed value (inclusive). - #[serde(skip_serializing_if = "Option::is_none")] - pub maximum: Option, - /// Minimum allowed value (inclusive). - #[serde(skip_serializing_if = "Option::is_none")] - pub minimum: Option, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Numeric type accepted by the field. - pub r#type: UIElicitationSchemaPropertyNumberType, +pub struct SessionsFindByTaskIDRequest { + /// GitHub task ID to look up + pub task_id: String, } -/// Free-text string field with optional length and format constraints. +/// ID of the local session bound to the given GitHub task, or omitted when none. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationSchemaPropertyString { - /// Default value populated in the input when the form is first shown. - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - /// Help text describing the field. +pub struct SessionsFindByTaskIDResult { + /// Omitted when no local session is bound to that GitHub task #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Optional format hint that constrains the accepted input. - #[serde(skip_serializing_if = "Option::is_none")] - pub format: Option, - /// Maximum number of characters allowed. - #[serde(skip_serializing_if = "Option::is_none")] - pub max_length: Option, - /// Minimum number of characters required. - #[serde(skip_serializing_if = "Option::is_none")] - pub min_length: Option, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "string". - pub r#type: UIElicitationSchemaPropertyStringType, + pub session_id: Option, } -/// Single-select string field whose allowed values are defined inline. +/// Source session identifier to fork from, optional event-ID boundary, and optional friendly name for the new session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationStringEnumField { - /// Default value selected when the form is first shown. - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - /// Help text describing the field. +pub struct SessionsForkRequest { + /// Optional friendly name to assign to the forked session. #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Allowed string values. - pub r#enum: Vec, - /// Optional display labels for each enum value, in the same order as `enum`. - #[serde(default)] - pub enum_names: Vec, - /// Human-readable label for the field. + pub name: Option, + /// Source session ID to fork from + pub session_id: SessionId, + /// Optional event ID boundary. When provided, the fork includes only events before this ID (exclusive). When omitted, all events are included. #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "string". - pub r#type: UIElicitationStringEnumFieldType, + pub to_event_id: Option, } -/// Schema for the `UIElicitationStringOneOfFieldOneOf` type. +/// Identifier and optional friendly name assigned to the newly forked session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationStringOneOfFieldOneOf { - /// Value submitted when this option is selected. - pub r#const: String, - /// Display label for this option. - pub title: String, +pub struct SessionsForkResult { + /// Friendly name assigned to the forked session, if any. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// The new forked session's ID + pub session_id: SessionId, +} + +/// Session ID whose event-log file path to compute. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetEventFilePathRequest { + /// Session ID whose event-log file path to compute + pub session_id: SessionId, +} + +/// Absolute path to the session's events.jsonl file on disk. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetEventFilePathResult { + /// Absolute path to the session's events.jsonl file + pub file_path: String, +} + +/// Optional working-directory context used to score session relevance. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetLastForContextRequest { + /// Optional working-directory context used to score session relevance. When omitted the most-recently-modified session wins. + #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option, +} + +/// Most-relevant session ID for the supplied context, or omitted when no sessions exist. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetLastForContextResult { + /// Most-relevant session ID for the supplied context, or omitted when no sessions exist + #[serde(skip_serializing_if = "Option::is_none")] + pub session_id: Option, +} + +/// Session ID to look up the persisted remote-steerable flag for. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetPersistedRemoteSteerableRequest { + /// Session ID to look up the persisted remote-steerable flag for + pub session_id: SessionId, +} + +/// The session's persisted remote-steerable flag, or omitted when no value has been persisted. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetPersistedRemoteSteerableResult { + /// The session's persisted remote-steerable flag if recorded; omitted when no value has been persisted + #[serde(skip_serializing_if = "Option::is_none")] + pub remote_steerable: Option, +} + +/// Map of sessionId -> on-disk size in bytes for each session's workspace directory. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSizes { + /// Map of sessionId -> on-disk size in bytes for the session's workspace directory + pub sizes: HashMap, +} + +/// Optional filter applied to the returned sessions +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsListRequestFilter { + /// Match sessions whose context.branch equals this value + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + /// Match sessions whose context.cwd equals this value + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + /// Match sessions whose context.gitRoot equals this value + #[serde(skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Match sessions whose context.repository equals this value + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, +} + +/// Optional metadata-load limit and context filter applied to the returned sessions. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsListRequest { + /// Optional filter applied to the returned sessions + #[serde(skip_serializing_if = "Option::is_none")] + pub filter: Option, + /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata_limit: Option, +} + +/// Active session ID whose deferred repo-level hooks should be loaded. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsLoadDeferredRepoHooksRequest { + /// Active session ID whose deferred repo-level hooks should be loaded + pub session_id: SessionId, +} + +/// Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsPruneOldRequest { + /// When true, only report what would be deleted without performing any deletion + #[serde(skip_serializing_if = "Option::is_none")] + pub dry_run: Option, + /// Session IDs that should never be considered for pruning + #[serde(default)] + pub exclude_session_ids: Vec, + /// When true, named sessions (set via /rename) are also eligible for pruning + #[serde(skip_serializing_if = "Option::is_none")] + pub include_named: Option, + /// Delete sessions whose modifiedTime is at least this many days old + pub older_than_days: i64, +} + +/// Session ID whose in-use lock should be released. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsReleaseLockRequest { + /// Session ID whose in-use lock should be released + pub session_id: SessionId, +} + +/// Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsReleaseLockResult {} + +/// Active session ID and an optional flag for deferring repo-level hooks until folder trust. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsReloadPluginHooksRequest { + /// When true, skip repo-level hooks. Use before folder trust is confirmed; loadDeferredRepoHooks loads them post-trust. + #[serde(skip_serializing_if = "Option::is_none")] + pub defer_repo_hooks: Option, + /// Active session ID to reload hooks for + pub session_id: SessionId, +} + +/// Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsReloadPluginHooksResult {} + +/// Session ID whose pending events should be flushed to disk. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsSaveRequest { + /// Session ID whose pending events should be flushed to disk + pub session_id: SessionId, +} + +/// Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsSaveResult {} + +/// Manager-wide additional plugins to register; replaces any previously-configured set. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsSetAdditionalPluginsRequest { + /// Manager-wide additional plugins to register. Replaces any previously-configured set. Pass an empty array to clear. + pub plugins: Vec, +} + +/// Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsSetAdditionalPluginsResult {} + +/// Patch of mutable session options to apply to the running session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionUpdateOptionsParams { + /// Additional content-exclusion policies to merge into the session's policy set. Opaque shape; see `ContentExclusionApiResponse` in the runtime. + #[serde(default)] + pub additional_content_exclusion_policies: Vec, + /// Runtime context discriminator (e.g., `cli`, `actions`). + #[serde(skip_serializing_if = "Option::is_none")] + pub agent_context: Option, + /// Whether to disable the `ask_user` tool (encourages autonomous behavior). + #[serde(skip_serializing_if = "Option::is_none")] + pub ask_user_disabled: Option, + /// Allowlist of tool names available to this session. + #[serde(default)] + pub available_tools: Vec, + /// Identifier of the client driving the session. + #[serde(skip_serializing_if = "Option::is_none")] + pub client_name: Option, + /// Whether to include the `Co-authored-by` trailer in commit messages. + #[serde(skip_serializing_if = "Option::is_none")] + pub coauthor_enabled: Option, + /// Whether to allow auto-mode continuation across turns. + #[serde(skip_serializing_if = "Option::is_none")] + pub continue_on_auto_mode: Option, + /// Override URL for the Copilot API endpoint. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_url: Option, + /// Whether to default custom agents to local-only execution. + #[serde(skip_serializing_if = "Option::is_none")] + pub custom_agents_local_only: Option, + /// Instruction source IDs to exclude from the system prompt. + #[serde(default)] + pub disabled_instruction_sources: Vec, + /// Skill IDs that should be excluded from this session. + #[serde(default)] + pub disabled_skills: Vec, + /// Whether to discover custom instructions on demand after successful file views (AGENTS.md / CLAUDE.md / .github/copilot-instructions.md surfacing). Combined with `skipCustomInstructions` and the runtime-side `ON_DEMAND_INSTRUCTIONS` feature flag. + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_on_demand_instruction_discovery: Option, + /// Whether to surface reasoning-summary events from the model. + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_reasoning_summaries: Option, + /// Whether shell-script safety heuristics are enabled. + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_script_safety: Option, + /// Whether to stream model responses. + #[serde(skip_serializing_if = "Option::is_none")] + pub enable_streaming: Option, + /// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). + #[serde(skip_serializing_if = "Option::is_none")] + pub env_value_mode: Option, + /// Override directory for the session-events log. When unset, the runtime's default events log directory is used. + #[serde(skip_serializing_if = "Option::is_none")] + pub events_log_directory: Option, + /// Denylist of tool names for this session. + #[serde(default)] + pub excluded_tools: Vec, + /// Map of feature-flag IDs to their boolean enabled state. + #[serde(default)] + pub feature_flags: HashMap, + /// Full set of installed plugins for the session. Replaces the existing list; the runtime invalidates the skills cache only when the list materially changes. + #[serde(default)] + pub installed_plugins: Vec, + /// Stable integration identifier used for analytics and rate-limit attribution. + #[serde(skip_serializing_if = "Option::is_none")] + pub integration_id: Option, + /// Whether experimental capabilities are enabled. + #[serde(skip_serializing_if = "Option::is_none")] + pub is_experimental_mode: Option, + /// Whether interactive shell sessions are logged. + #[serde(skip_serializing_if = "Option::is_none")] + pub log_interactive_shells: Option, + /// Identifier sent to LSP-style integrations. + #[serde(skip_serializing_if = "Option::is_none")] + pub lsp_client_name: Option, + /// Whether to expose the `manage_schedule` tool to the agent. The runtime always owns the per-session schedule registry; this flag only controls tool exposure (typically gated to staff users). + #[serde(skip_serializing_if = "Option::is_none")] + pub manage_schedule_enabled: Option, + /// The model ID to use for assistant turns. + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, + /// Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the runtime. + #[serde(skip_serializing_if = "Option::is_none")] + pub provider: Option, + /// Reasoning effort for the selected model (model-defined enum). + #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning_effort: Option, + /// Whether the session is running in an interactive UI. + #[serde(skip_serializing_if = "Option::is_none")] + pub running_in_interactive_mode: Option, + /// Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. + #[serde(skip_serializing_if = "Option::is_none")] + pub sandbox_config: Option, + /// Shell init profile (`None` or `NonInteractive`). + #[serde(skip_serializing_if = "Option::is_none")] + pub shell_init_profile: Option, + /// Per-shell process flags (e.g., `pwsh` arguments). + #[serde(default)] + pub shell_process_flags: Vec, + /// Additional directories to search for skills. + #[serde(default)] + pub skill_directories: Vec, + /// Whether to skip loading custom instruction sources. + #[serde(skip_serializing_if = "Option::is_none")] + pub skip_custom_instructions: Option, + /// Optional path for trajectory output. + #[serde(skip_serializing_if = "Option::is_none")] + pub trajectory_file: Option, + /// Absolute working-directory path for shell tools. + #[serde(skip_serializing_if = "Option::is_none")] + pub working_directory: Option, +} + +/// Indicates whether the session options patch was applied successfully. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionUpdateOptionsResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Shell command to run, with optional working directory and timeout in milliseconds. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShellExecRequest { + /// Shell command to execute + pub command: String, + /// Working directory (defaults to session working directory) + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + /// Timeout in milliseconds (default: 30000) + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, +} + +/// Identifier of the spawned process, used to correlate streamed output and exit notifications. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShellExecResult { + /// Unique identifier for tracking streamed output + pub process_id: String, +} + +/// Identifier of a process previously returned by "shell.exec" and the signal to send. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShellKillRequest { + /// Process identifier returned by shell.exec + pub process_id: String, + /// Signal to send (default: SIGTERM) + #[serde(skip_serializing_if = "Option::is_none")] + pub signal: Option, +} + +/// Indicates whether the signal was delivered; false if the process was unknown or already exited. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShellKillResult { + /// Whether the signal was sent successfully + pub killed: bool, +} + +/// Parameters for shutting down the session +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShutdownRequest { + /// Optional human-readable reason. Typically the message of the error that triggered shutdown when type is 'error'. + #[serde(skip_serializing_if = "Option::is_none")] + pub reason: Option, + /// Why the session is being shut down. Defaults to "routine" when omitted. + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option, +} + +/// Schema for the `Skill` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Skill { + /// Description of what the skill does + pub description: String, + /// Whether the skill is currently enabled + pub enabled: bool, + /// Unique identifier for the skill + pub name: String, + /// Absolute path to the skill file + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + /// Name of the plugin that provides the skill, when source is 'plugin' + #[serde(skip_serializing_if = "Option::is_none")] + pub plugin_name: Option, + /// Source location type (e.g., project, personal-copilot, plugin, builtin) + pub source: SkillSource, + /// Whether the skill can be invoked by the user as a slash command + pub user_invocable: bool, +} + +/// Skills available to the session, with their enabled state. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillList { + /// Available skills + pub skills: Vec, +} + +/// Skill names to mark as disabled in global configuration, replacing any previous list. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsConfigSetDisabledSkillsRequest { + /// List of skill names to disable + pub disabled_skills: Vec, +} + +/// Name of the skill to disable for the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsDisableRequest { + /// Name of the skill to disable + pub name: String, +} + +/// Optional project paths and additional skill directories to include in discovery. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsDiscoverRequest { + /// Optional list of project directory paths to scan for project-scoped skills + #[serde(default)] + pub project_paths: Vec, + /// Optional list of additional skill directory paths to include + #[serde(default)] + pub skill_directories: Vec, +} + +/// Name of the skill to enable for the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsEnableRequest { + /// Name of the skill to enable + pub name: String, +} + +/// Schema for the `SkillsInvokedSkill` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsInvokedSkill { + /// Tools that should be auto-approved when this skill is active, captured at invocation time + #[serde(default)] + pub allowed_tools: Vec, + /// Full content of the skill file + pub content: String, + /// Turn number when the skill was invoked + pub invoked_at_turn: i64, + /// Unique identifier for the skill + pub name: String, + /// Path to the SKILL.md file + pub path: String, +} + +/// Skills invoked during this session, ordered by invocation time (most recent last). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsGetInvokedResult { + /// Skills invoked during this session, ordered by invocation time (most recent last) + pub skills: Vec, +} + +/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsLoadDiagnostics { + /// Errors emitted while loading skills (e.g. skills that failed to load entirely) + pub errors: Vec, + /// Warnings emitted while loading skills (e.g. skills that loaded but had issues) + pub warnings: Vec, +} + +/// Schema for the `SlashCommandAgentPromptResult` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SlashCommandAgentPromptResult { + /// Prompt text to display to the user + pub display_prompt: String, + /// Agent prompt result discriminator + pub kind: SlashCommandAgentPromptResultKind, + /// Optional target session mode for the agent prompt + #[serde(skip_serializing_if = "Option::is_none")] + pub mode: Option, + /// Prompt to submit to the agent + pub prompt: String, + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh + #[serde(skip_serializing_if = "Option::is_none")] + pub runtime_settings_changed: Option, +} + +/// Schema for the `SlashCommandCompletedResult` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SlashCommandCompletedResult { + /// Completed result discriminator + pub kind: SlashCommandCompletedResultKind, + /// Optional user-facing message describing the completed command + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh + #[serde(skip_serializing_if = "Option::is_none")] + pub runtime_settings_changed: Option, +} + +/// Schema for the `SlashCommandTextResult` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SlashCommandTextResult { + /// Text result discriminator + pub kind: SlashCommandTextResultKind, + /// Whether text contains Markdown + #[serde(skip_serializing_if = "Option::is_none")] + pub markdown: Option, + /// Whether ANSI sequences should be preserved + #[serde(skip_serializing_if = "Option::is_none")] + pub preserve_ansi: Option, + /// True when the invocation mutated user runtime settings; consumers caching settings should refresh + #[serde(skip_serializing_if = "Option::is_none")] + pub runtime_settings_changed: Option, + /// Text output for the client to render + pub text: String, +} + +/// Schema for the `TaskAgentInfo` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TaskAgentInfo { + /// ISO 8601 timestamp when the current active period began + #[serde(skip_serializing_if = "Option::is_none")] + pub active_started_at: Option, + /// Accumulated active execution time in milliseconds + #[serde(skip_serializing_if = "Option::is_none")] + pub active_time_ms: Option, + /// Type of agent running this task + pub agent_type: String, + /// Whether the task is currently in the original sync wait and can be moved to background mode. False once it is already backgrounded, idle, finished, or no longer has a promotable sync waiter. + #[serde(skip_serializing_if = "Option::is_none")] + pub can_promote_to_background: Option, + /// ISO 8601 timestamp when the task finished + #[serde(skip_serializing_if = "Option::is_none")] + pub completed_at: Option, + /// Short description of the task + pub description: String, + /// Error message when the task failed + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether task execution is synchronously awaited or managed in the background + #[serde(skip_serializing_if = "Option::is_none")] + pub execution_mode: Option, + /// Unique task identifier + pub id: String, + /// ISO 8601 timestamp when the agent entered idle state + #[serde(skip_serializing_if = "Option::is_none")] + pub idle_since: Option, + /// Most recent response text from the agent + #[serde(skip_serializing_if = "Option::is_none")] + pub latest_response: Option, + /// Model used for the task when specified + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, + /// Prompt passed to the agent + pub prompt: String, + /// Result text from the task when available + #[serde(skip_serializing_if = "Option::is_none")] + pub result: Option, + /// ISO 8601 timestamp when the task was started + pub started_at: String, + /// Current lifecycle status of the task + pub status: TaskStatus, + /// Tool call ID associated with this agent task + pub tool_call_id: String, + /// Task kind + pub r#type: TaskAgentInfoType, +} + +/// Background tasks currently tracked by the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TaskList { + /// Currently tracked tasks + pub tasks: Vec, +} + +/// Identifier of the background task to cancel. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksCancelRequest { + /// Task identifier + pub id: String, +} + +/// Indicates whether the background task was successfully cancelled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksCancelResult { + /// Whether the task was successfully cancelled + pub cancelled: bool, +} + +/// The first sync-waiting task that can currently be promoted to background mode. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksGetCurrentPromotableResult { + /// The first sync-waiting task (agent first, then shell) that can currently be promoted to background mode. Omitted if no such task exists. The returned task is guaranteed to have executionMode='sync' and canPromoteToBackground=true at the time of the call. + #[serde(skip_serializing_if = "Option::is_none")] + pub task: Option, +} + +/// Identifier of the background task to fetch progress for. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksGetProgressRequest { + /// Task identifier (agent ID or shell ID) + pub id: String, +} + +/// Progress information for the task, or null when no task with that ID is tracked. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksGetProgressResult { + /// Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. + pub progress: serde_json::Value, +} + +/// Schema for the `TaskShellInfo` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TaskShellInfo { + /// Whether the shell runs inside a managed PTY session or as an independent background process + pub attachment_mode: TaskShellInfoAttachmentMode, + /// Whether this shell task can be promoted to background mode + #[serde(skip_serializing_if = "Option::is_none")] + pub can_promote_to_background: Option, + /// Command being executed + pub command: String, + /// ISO 8601 timestamp when the task finished + #[serde(skip_serializing_if = "Option::is_none")] + pub completed_at: Option, + /// Short description of the task + pub description: String, + /// Whether task execution is synchronously awaited or managed in the background + #[serde(skip_serializing_if = "Option::is_none")] + pub execution_mode: Option, + /// Unique task identifier + pub id: String, + /// Path to the detached shell log, when available + #[serde(skip_serializing_if = "Option::is_none")] + pub log_path: Option, + /// Process ID when available + #[serde(skip_serializing_if = "Option::is_none")] + pub pid: Option, + /// ISO 8601 timestamp when the task was started + pub started_at: String, + /// Current lifecycle status of the task + pub status: TaskStatus, + /// Task kind + pub r#type: TaskShellInfoType, +} + +/// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksPromoteCurrentToBackgroundResult { + /// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. Atomic operation: avoids the race window of getCurrentPromotable + promoteToBackground. + #[serde(skip_serializing_if = "Option::is_none")] + pub task: Option, +} + +/// Identifier of the task to promote to background mode. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksPromoteToBackgroundRequest { + /// Task identifier + pub id: String, +} + +/// Indicates whether the task was successfully promoted to background mode. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksPromoteToBackgroundResult { + /// Whether the task was successfully promoted to background mode + pub promoted: bool, +} + +/// Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksRefreshResult {} + +/// Identifier of the completed or cancelled task to remove from tracking. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksRemoveRequest { + /// Task identifier + pub id: String, +} + +/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksRemoveResult { + /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). + pub removed: bool, +} + +/// Identifier of the target agent task, message content, and optional sender agent ID. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksSendMessageRequest { + /// Agent ID of the sender, if sent on behalf of another agent + #[serde(skip_serializing_if = "Option::is_none")] + pub from_agent_id: Option, + /// Agent task identifier + pub id: String, + /// Message content to send to the agent + pub message: String, +} + +/// Indicates whether the message was delivered, with an error message when delivery failed. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksSendMessageResult { + /// Error message if delivery failed + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether the message was successfully delivered or steered + pub sent: bool, +} + +/// Agent type, prompt, name, and optional description and model override for the new task. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksStartAgentRequest { + /// Type of agent to start (e.g., 'explore', 'task', 'general-purpose') + pub agent_type: String, + /// Short description of the task + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Optional model override + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, + /// Short name for the agent, used to generate a human-readable ID + pub name: String, + /// Task prompt for the agent + pub prompt: String, +} + +/// Identifier assigned to the newly started background agent task. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksStartAgentResult { + /// Generated agent ID for the background task + pub agent_id: String, +} + +/// Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TasksWaitForPendingResult {} + +/// Feature override key/value pairs to attach to subsequent telemetry events from this session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TelemetrySetFeatureOverridesRequest { + /// Override key/value pairs to attach to subsequent telemetry events from this session. Replaces any previously-set overrides. + pub features: HashMap, +} + +/// Schema for the `TokenAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TokenAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Authentication host. + pub host: String, + /// The token value itself. Treat as a secret. + pub token: String, + /// SDK-side token authentication; the host configured the token directly via the SDK. + pub r#type: TokenAuthInfoType, +} + +/// Schema for the `Tool` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Tool { + /// Description of what the tool does + pub description: String, + /// Optional instructions for how to use this tool effectively + #[serde(skip_serializing_if = "Option::is_none")] + pub instructions: Option, + /// Tool identifier (e.g., "bash", "grep", "str_replace_editor") + pub name: String, + /// Optional namespaced name for declarative filtering (e.g., "playwright/navigate" for MCP tools) + #[serde(skip_serializing_if = "Option::is_none")] + pub namespaced_name: Option, + /// JSON Schema for the tool's input parameters + #[serde(default)] + pub parameters: HashMap, +} + +/// Built-in tools available for the requested model, with their parameters and instructions. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ToolList { + /// List of available built-in tools with metadata + pub tools: Vec, +} + +/// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ToolsInitializeAndValidateResult {} + +/// Optional model identifier whose tool overrides should be applied to the listing. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ToolsListRequest { + /// Optional model ID — when provided, the returned tool list reflects model-specific overrides + #[serde(skip_serializing_if = "Option::is_none")] + pub model: Option, +} + +/// Schema for the `UIElicitationArrayAnyOfFieldItemsAnyOf` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationArrayAnyOfFieldItemsAnyOf { + /// Value submitted when this option is selected. + pub r#const: String, + /// Display label for this option. + pub title: String, +} + +/// Schema applied to each item in the array. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationArrayAnyOfFieldItems { + /// Selectable options, each with a value and a display label. + pub any_of: Vec, +} + +/// Multi-select string field where each option pairs a value with a display label. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationArrayAnyOfField { + /// Default values selected when the form is first shown. + #[serde(default)] + pub default: Vec, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Schema applied to each item in the array. + pub items: UIElicitationArrayAnyOfFieldItems, + /// Maximum number of items the user may select. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_items: Option, + /// Minimum number of items the user must select. + #[serde(skip_serializing_if = "Option::is_none")] + pub min_items: Option, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "array". + pub r#type: UIElicitationArrayAnyOfFieldType, +} + +/// Schema applied to each item in the array. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationArrayEnumFieldItems { + /// Allowed string values for each selected item. + pub r#enum: Vec, + /// Type discriminator. Always "string". + pub r#type: UIElicitationArrayEnumFieldItemsType, +} + +/// Multi-select string field whose allowed values are defined inline. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationArrayEnumField { + /// Default values selected when the form is first shown. + #[serde(default)] + pub default: Vec, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Schema applied to each item in the array. + pub items: UIElicitationArrayEnumFieldItems, + /// Maximum number of items the user may select. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_items: Option, + /// Minimum number of items the user must select. + #[serde(skip_serializing_if = "Option::is_none")] + pub min_items: Option, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "array". + pub r#type: UIElicitationArrayEnumFieldType, +} + +/// JSON Schema describing the form fields to present to the user +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationSchema { + /// Form field definitions, keyed by field name + pub properties: HashMap, + /// List of required field names + #[serde(default)] + pub required: Vec, + /// Schema type indicator (always 'object') + pub r#type: UIElicitationSchemaType, +} + +/// Prompt message and JSON schema describing the form fields to elicit from the user. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationRequest { + /// Message describing what information is needed from the user + pub message: String, + /// JSON Schema describing the form fields to present to the user + pub requested_schema: UIElicitationSchema, +} + +/// The elicitation response (accept with form values, decline, or cancel) +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationResponse { + /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed) + pub action: UIElicitationResponseAction, + /// The form values submitted by the user (present when action is 'accept') + #[serde(default)] + pub content: HashMap, +} + +/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationResult { + /// Whether the response was accepted. False if the request was already resolved by another client. + pub success: bool, +} + +/// Boolean field rendered as a yes/no toggle. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationSchemaPropertyBoolean { + /// Default value selected when the form is first shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub default: Option, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "boolean". + pub r#type: UIElicitationSchemaPropertyBooleanType, +} + +/// Numeric field accepting either a number or an integer. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationSchemaPropertyNumber { + /// Default value populated in the input when the form is first shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub default: Option, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Maximum allowed value (inclusive). + #[serde(skip_serializing_if = "Option::is_none")] + pub maximum: Option, + /// Minimum allowed value (inclusive). + #[serde(skip_serializing_if = "Option::is_none")] + pub minimum: Option, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Numeric type accepted by the field. + pub r#type: UIElicitationSchemaPropertyNumberType, +} + +/// Free-text string field with optional length and format constraints. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationSchemaPropertyString { + /// Default value populated in the input when the form is first shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub default: Option, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Optional format hint that constrains the accepted input. + #[serde(skip_serializing_if = "Option::is_none")] + pub format: Option, + /// Maximum number of characters allowed. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_length: Option, + /// Minimum number of characters required. + #[serde(skip_serializing_if = "Option::is_none")] + pub min_length: Option, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "string". + pub r#type: UIElicitationSchemaPropertyStringType, +} + +/// Single-select string field whose allowed values are defined inline. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationStringEnumField { + /// Default value selected when the form is first shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub default: Option, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Allowed string values. + pub r#enum: Vec, + /// Optional display labels for each enum value, in the same order as `enum`. + #[serde(default)] + pub enum_names: Vec, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "string". + pub r#type: UIElicitationStringEnumFieldType, +} + +/// Schema for the `UIElicitationStringOneOfFieldOneOf` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationStringOneOfFieldOneOf { + /// Value submitted when this option is selected. + pub r#const: String, + /// Display label for this option. + pub title: String, +} + +/// Single-select string field where each option pairs a value with a display label. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIElicitationStringOneOfField { + /// Default value selected when the form is first shown. + #[serde(skip_serializing_if = "Option::is_none")] + pub default: Option, + /// Help text describing the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + /// Selectable options, each with a value and a display label. + pub one_of: Vec, + /// Human-readable label for the field. + #[serde(skip_serializing_if = "Option::is_none")] + pub title: Option, + /// Type discriminator. Always "string". + pub r#type: UIElicitationStringOneOfFieldType, +} + +/// Schema for the `UIExitPlanModeResponse` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIExitPlanModeResponse { + /// Whether the plan was approved. + pub approved: bool, + /// Whether subsequent edits should be auto-approved without confirmation. + #[serde(skip_serializing_if = "Option::is_none")] + pub auto_approve_edits: Option, + /// Feedback from the user when they declined the plan or requested changes. + #[serde(skip_serializing_if = "Option::is_none")] + pub feedback: Option, + /// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. + #[serde(skip_serializing_if = "Option::is_none")] + pub selected_action: Option, +} + +/// Request ID of a pending `auto_mode_switch.requested` event and the user's response. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingAutoModeSwitchRequest { + /// The unique request ID from the auto_mode_switch.requested event + pub request_id: RequestId, + /// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). + pub response: UIAutoModeSwitchResponse, +} + +/// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingElicitationRequest { + /// The unique request ID from the elicitation.requested event + pub request_id: RequestId, + /// The elicitation response (accept with form values, decline, or cancel) + pub result: UIElicitationResponse, +} + +/// Request ID of a pending `exit_plan_mode.requested` event and the user's response. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingExitPlanModeRequest { + /// The unique request ID from the exit_plan_mode.requested event + pub request_id: RequestId, + /// Schema for the `UIExitPlanModeResponse` type. + pub response: UIExitPlanModeResponse, +} + +/// Indicates whether the pending UI request was resolved by this call. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingResult { + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + pub success: bool, +} + +/// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingSamplingResponse {} + +/// Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingSamplingRequest { + /// The unique request ID from the sampling.requested event + pub request_id: RequestId, + /// Optional sampling result payload. Omit to reject/cancel the sampling request without providing a result. + #[serde(skip_serializing_if = "Option::is_none")] + pub response: Option, +} + +/// Schema for the `UIUserInputResponse` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIUserInputResponse { + /// The user's answer text + pub answer: String, + /// True if the user typed a freeform response, false if they selected a presented choice. Used by telemetry to differentiate between free text input and choice selection. + pub was_freeform: bool, +} + +/// Request ID of a pending `user_input.requested` event and the user's response. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIHandlePendingUserInputRequest { + /// The unique request ID from the user_input.requested event + pub request_id: RequestId, + /// Schema for the `UIUserInputResponse` type. + pub response: UIUserInputResponse, +} + +/// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIRegisterDirectAutoModeSwitchHandlerResult { + /// Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. + pub handle: String, +} + +/// Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIUnregisterDirectAutoModeSwitchHandlerRequest { + /// Handle previously returned by `registerDirectAutoModeSwitchHandler` + pub handle: String, +} + +/// Indicates whether the handle was active and the registration count was decremented. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UIUnregisterDirectAutoModeSwitchHandlerResult { + /// True if the handle was active and decremented the counter; false if the handle was unknown. + pub unregistered: bool, +} + +/// Aggregated code change metrics +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsCodeChanges { + /// Distinct file paths modified during the session + pub files_modified: Vec, + /// Number of distinct files modified + pub files_modified_count: i64, + /// Total lines of code added + pub lines_added: i64, + /// Total lines of code removed + pub lines_removed: i64, +} + +/// Request count and cost metrics for this model +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsModelMetricRequests { + /// User-initiated premium request cost (with multiplier applied) + pub cost: f64, + /// Number of API requests made with this model + pub count: i64, +} + +/// Schema for the `UsageMetricsModelMetricTokenDetail` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsModelMetricTokenDetail { + /// Accumulated token count for this token type + pub token_count: i64, +} + +/// Token usage metrics for this model +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsModelMetricUsage { + /// Total tokens read from prompt cache + pub cache_read_tokens: i64, + /// Total tokens written to prompt cache + pub cache_write_tokens: i64, + /// Total input tokens consumed + pub input_tokens: i64, + /// Total output tokens produced + pub output_tokens: i64, + /// Total output tokens used for reasoning + #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning_tokens: Option, +} + +/// Schema for the `UsageMetricsModelMetric` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsModelMetric { + /// Request count and cost metrics for this model + pub requests: UsageMetricsModelMetricRequests, + /// Token count details per type + #[serde(default)] + pub token_details: HashMap, + /// Accumulated nano-AI units cost for this model + #[serde(skip_serializing_if = "Option::is_none")] + pub total_nano_aiu: Option, + /// Token usage metrics for this model + pub usage: UsageMetricsModelMetricUsage, +} + +/// Schema for the `UsageMetricsTokenDetail` type. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageMetricsTokenDetail { + /// Accumulated token count for this token type + pub token_count: i64, +} + +/// Accumulated session usage metrics, including premium request cost, token counts, model breakdown, and code-change totals. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UsageGetMetricsResult { + /// Aggregated code change metrics + pub code_changes: UsageMetricsCodeChanges, + /// Currently active model identifier + #[serde(skip_serializing_if = "Option::is_none")] + pub current_model: Option, + /// Input tokens from the most recent main-agent API call + pub last_call_input_tokens: i64, + /// Output tokens from the most recent main-agent API call + pub last_call_output_tokens: i64, + /// Per-model token and request metrics, keyed by model identifier + pub model_metrics: HashMap, + /// ISO 8601 timestamp when the session started + pub session_start_time: String, + /// Session-wide per-token-type accumulated token counts + #[serde(default)] + pub token_details: HashMap, + /// Total time spent in model API calls (milliseconds) + pub total_api_duration_ms: i64, + /// Session-wide accumulated nano-AI units cost + #[serde(skip_serializing_if = "Option::is_none")] + pub total_nano_aiu: Option, + /// Total user-initiated premium request cost across all models (may be fractional due to multipliers) + pub total_premium_request_cost: f64, + /// Raw count of user-initiated API requests + pub total_user_requests: i64, +} + +/// Schema for the `UserAuthInfo` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UserAuthInfo { + /// Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set. + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_user: Option, + /// Authentication host. + pub host: String, + /// OAuth user login. + pub login: String, + /// OAuth user authentication. The token itself is held in the runtime's secret token store (keyed by host+login) and is NOT carried in this struct. + pub r#type: UserAuthInfoType, +} + +/// Schema for the `WorkspacesCheckpoints` type. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesCheckpoints { + /// Filename of the checkpoint within the workspace checkpoints directory + pub filename: String, + /// Checkpoint number assigned by the workspace manager + pub number: i64, + /// Human-readable checkpoint title + pub title: String, +} + +/// Relative path and UTF-8 content for the workspace file to create or overwrite. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesCreateFileRequest { + /// File content to write as a UTF-8 string + pub content: String, + /// Relative path within the workspace files directory + pub path: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesGetWorkspaceResultWorkspace { + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + #[serde( + rename = "chronicle_sync_dismissed", + skip_serializing_if = "Option::is_none" + )] + pub chronicle_sync_dismissed: Option, + #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] + pub created_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] + pub git_root: Option, + #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] + pub host_type: Option, + pub id: String, + #[serde(rename = "mc_last_event_id", skip_serializing_if = "Option::is_none")] + pub mc_last_event_id: Option, + #[serde(rename = "mc_session_id", skip_serializing_if = "Option::is_none")] + pub mc_session_id: Option, + #[serde(rename = "mc_task_id", skip_serializing_if = "Option::is_none")] + pub mc_task_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "remote_steerable", skip_serializing_if = "Option::is_none")] + pub remote_steerable: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + #[serde(rename = "summary_count", skip_serializing_if = "Option::is_none")] + pub summary_count: Option, + #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + #[serde(rename = "user_named", skip_serializing_if = "Option::is_none")] + pub user_named: Option, +} + +/// Current workspace metadata for the session, including its absolute filesystem path when available. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesGetWorkspaceResult { + /// Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + /// Current workspace metadata, or null if not available + pub workspace: Option, +} + +/// Workspace checkpoints in chronological order; empty when the workspace is not enabled. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesListCheckpointsResult { + /// Workspace checkpoints in chronological order. Empty when workspace is not enabled. + pub checkpoints: Vec, +} + +/// Relative paths of files stored in the session workspace files directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesListFilesResult { + /// Relative file paths in the workspace files directory + pub files: Vec, +} + +/// Checkpoint number to read. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesReadCheckpointRequest { + /// Checkpoint number to read + pub number: i64, +} + +/// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesReadCheckpointResult { + /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing + pub content: Option, +} + +/// Relative path of the workspace file to read. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesReadFileRequest { + /// Relative path within the workspace files directory + pub path: String, +} + +/// Contents of the requested workspace file as a UTF-8 string. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesReadFileResult { + /// File content as a UTF-8 string + pub content: String, +} + +/// Pasted content to save as a UTF-8 file in the session workspace. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesSaveLargePasteRequest { + /// Pasted content to save as a UTF-8 file + pub content: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesSaveLargePasteResultSaved { + /// Filename within the workspace files directory + pub filename: String, + /// Absolute filesystem path to the saved paste file + pub file_path: String, + /// Size of the saved file in bytes + pub size_bytes: i64, +} + +/// Descriptor for the saved paste file, or null when the workspace is unavailable. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspacesSaveLargePasteResult { + /// Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions) + pub saved: Option, +} + +/// Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WorkspaceSummary { + /// Branch checked out at session start, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + /// ISO 8601 timestamp when the workspace was created + #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] + pub created_at: Option, + /// Current working directory at session start + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + /// Resolved git root for cwd, if any + #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Repository host type, if known + #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] + pub host_type: Option, + /// Workspace identifier (1:1 with sessionId) + pub id: String, + /// Display name for the session, if set + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// Repository identifier in 'owner/repo' or 'org/project/repo' format, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + /// ISO 8601 timestamp when the workspace was last updated + #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] + pub updated_at: Option, +} + +/// List of Copilot models available to the resolved user, including capabilities and billing metadata. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ModelsListResult { + /// List of available models with full metadata + pub models: Vec, +} + +/// Built-in tools available for the requested model, with their parameters and instructions. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ToolsListResult { + /// List of available built-in tools with metadata + pub tools: Vec, +} + +/// User-configured MCP servers, keyed by server name. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct McpConfigListResult { + /// All MCP servers from user config, keyed by name + pub servers: HashMap, +} + +/// Skills discovered across global and project sources. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SkillsDiscoverResult { + /// All discovered skills across all sources + pub skills: Vec, +} + +/// Remote session connection result. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsConnectResult { + /// Metadata for a connected remote session. + pub metadata: ConnectedRemoteSessionMetadata, + /// SDK session ID for the connected remote session. + pub session_id: SessionId, +} + +/// Persisted sessions matching the filter, ordered most-recently-modified first. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsListResult { + /// Sessions ordered most-recently-modified first + pub sessions: Vec, +} + +/// ID of the local session bound to the given GitHub task, or omitted when none. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsFindByTaskIdResult { + /// Omitted when no local session is bound to that GitHub task + #[serde(skip_serializing_if = "Option::is_none")] + pub session_id: Option, +} + +/// Map of sessionId -> on-disk size in bytes for each session's workspace directory. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsGetSizesResult { + /// Map of sessionId -> on-disk size in bytes for the session's workspace directory + pub sizes: HashMap, +} + +/// Map of sessionId -> bytes freed by removing the session's workspace directory. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsBulkDeleteResult { + /// Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions whose deletion failed are omitted from this map (failures are logged on the server but not surfaced per-id; check the map for absent IDs to detect them). + pub freed_bytes: HashMap, +} + +/// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsPruneOldResult { + /// Session IDs that would be deleted in dry-run mode (always empty otherwise) + pub candidates: Vec, + /// Session IDs that were deleted (always empty in dry-run mode) + pub deleted: Vec, + /// True when no deletions were actually performed + pub dry_run: bool, + /// Total bytes freed (actual when not dry-run, projected when dry-run) + pub freed_bytes: i64, + /// Session IDs that were skipped (e.g., named sessions) + pub skipped: Vec, +} + +/// The same metadata records, with summary and context fields backfilled where available. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsEnrichMetadataResult { + /// Same records, with summary and context backfilled + pub sessions: Vec, +} + +/// Queued repo-level startup prompts and the total hook command count after loading. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionsLoadDeferredRepoHooksResult { + /// Total hook command count (user + plugin + repo) loaded for the session by this call. Captured atomically with startupPrompts so callers don't need to read a separate counter. + pub hook_count: i64, + /// Repo-level startup prompts queued from repo hook configs. Empty on resume, when no repo configs were pending, or when disableAllHooks is set. + pub startup_prompts: Vec, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSuspendParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Result of sending a user message +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSendResult { + /// Unique identifier assigned to the message + pub message_id: String, +} + +/// Result of aborting the current turn +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAbortResult { + /// Error message if the abort failed + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether the abort completed successfully + pub success: bool, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAuthGetStatusParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Authentication status and account metadata for the session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAuthGetStatusResult { + /// Authentication type + #[serde(skip_serializing_if = "Option::is_none")] + pub auth_type: Option, + /// Copilot plan tier (e.g., individual_pro, business) + #[serde(skip_serializing_if = "Option::is_none")] + pub copilot_plan: Option, + /// Authentication host URL + #[serde(skip_serializing_if = "Option::is_none")] + pub host: Option, + /// Whether the session has resolved authentication + pub is_authenticated: bool, + /// Authenticated login/username, if available + #[serde(skip_serializing_if = "Option::is_none")] + pub login: Option, + /// Human-readable authentication status description + #[serde(skip_serializing_if = "Option::is_none")] + pub status_message: Option, +} + +/// Indicates whether the credential update succeeded. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAuthSetCredentialsResult { + /// Whether the operation succeeded + pub success: bool, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionModelGetCurrentParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// The currently selected model and reasoning effort for the session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionModelGetCurrentResult { + /// Currently active model identifier + #[serde(skip_serializing_if = "Option::is_none")] + pub model_id: Option, + /// Reasoning effort level currently applied to the active model, when one is set. Reads `Session.getReasoningEffort()` synchronously after `getSelectedModel()` resolves so the two values are reported as a snapshot. + #[serde(skip_serializing_if = "Option::is_none")] + pub reasoning_effort: Option, +} + +/// The model identifier active on the session after the switch. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionModelSwitchToResult { + /// Currently active model identifier after the switch + #[serde(skip_serializing_if = "Option::is_none")] + pub model_id: Option, +} + +/// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionModelSetReasoningEffortResult { + /// Reasoning effort level recorded on the session after the update + pub reasoning_effort: String, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionModeGetParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionNameGetParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// The session's friendly name, or null when not yet set. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionNameGetResult { + /// The session name (user-set or auto-generated), or null if not yet set + pub name: Option, +} + +/// Indicates whether the auto-generated summary was applied as the session's name. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionNameSetAutoResult { + /// Whether the auto-generated summary was persisted. False if the session already has a user-set name, the summary normalized to empty, or the session does not have a workspace. + pub applied: bool, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionPlanReadParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Existence, contents, and resolved path of the session plan file. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionPlanReadResult { + /// The content of the plan file, or null if it does not exist + pub content: Option, + /// Whether the plan file exists in the workspace + pub exists: bool, + /// Absolute file path of the plan file, or null if workspace is not enabled + pub path: Option, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionPlanDeleteParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesGetWorkspaceParams { + /// Target session identifier + pub session_id: SessionId, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesGetWorkspaceResultWorkspace { + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + #[serde( + rename = "chronicle_sync_dismissed", + skip_serializing_if = "Option::is_none" + )] + pub chronicle_sync_dismissed: Option, + #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] + pub created_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] + pub git_root: Option, + #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] + pub host_type: Option, + pub id: String, + #[serde(rename = "mc_last_event_id", skip_serializing_if = "Option::is_none")] + pub mc_last_event_id: Option, + #[serde(rename = "mc_session_id", skip_serializing_if = "Option::is_none")] + pub mc_session_id: Option, + #[serde(rename = "mc_task_id", skip_serializing_if = "Option::is_none")] + pub mc_task_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "remote_steerable", skip_serializing_if = "Option::is_none")] + pub remote_steerable: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + #[serde(rename = "summary_count", skip_serializing_if = "Option::is_none")] + pub summary_count: Option, + #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] + pub updated_at: Option, + #[serde(rename = "user_named", skip_serializing_if = "Option::is_none")] + pub user_named: Option, +} + +/// Current workspace metadata for the session, including its absolute filesystem path when available. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesGetWorkspaceResult { + /// Absolute filesystem path to the workspace directory. Omitted when the session has no workspace (e.g. remote sessions). + #[serde(skip_serializing_if = "Option::is_none")] + pub path: Option, + /// Current workspace metadata, or null if not available + pub workspace: Option, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesListFilesParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Relative paths of files stored in the session workspace files directory. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesListFilesResult { + /// Relative file paths in the workspace files directory + pub files: Vec, +} + +/// Contents of the requested workspace file as a UTF-8 string. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesReadFileResult { + /// File content as a UTF-8 string + pub content: String, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesListCheckpointsParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Workspace checkpoints in chronological order; empty when the workspace is not enabled. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesListCheckpointsResult { + /// Workspace checkpoints in chronological order. Empty when workspace is not enabled. + pub checkpoints: Vec, +} + +/// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesReadCheckpointResult { + /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing + pub content: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesSaveLargePasteResultSaved { + /// Filename within the workspace files directory + pub filename: String, + /// Absolute filesystem path to the saved paste file + pub file_path: String, + /// Size of the saved file in bytes + pub size_bytes: i64, +} + +/// Descriptor for the saved paste file, or null when the workspace is unavailable. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionWorkspacesSaveLargePasteResult { + /// Saved-paste descriptor, or null when the workspace is unavailable (e.g. CCA runtime, non-infinite sessions, remote sessions) + pub saved: Option, +} + +/// Identifies the target session. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionInstructionsGetSourcesParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Instruction sources loaded for the session, in merge order. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionInstructionsGetSourcesResult { + /// Instruction sources for the session + pub sources: Vec, +} + +/// Indicates whether fleet mode was successfully activated. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionFleetStartResult { + /// Whether fleet mode was successfully activated + pub started: bool, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentListParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Custom agents available to the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentListResult { + /// Available custom agents + pub agents: Vec, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentGetCurrentParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// The currently selected custom agent, or null when using the default agent. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentGetCurrentResult { + /// Currently selected custom agent, or null if using the default agent + pub agent: AgentInfo, +} + +/// The newly selected custom agent. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentSelectResult { + /// The newly selected custom agent + pub agent: AgentInfo, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentDeselectParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentReloadParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Custom agents available to the session after reloading definitions from disk. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionAgentReloadResult { + /// Reloaded custom agents + pub agents: Vec, +} + +/// Identifier assigned to the newly started background agent task. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksStartAgentResult { + /// Generated agent ID for the background task + pub agent_id: String, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksListParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Background tasks currently tracked by the session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksListResult { + /// Currently tracked tasks + pub tasks: Vec, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksRefreshParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksRefreshResult {} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksWaitForPendingParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksWaitForPendingResult {} + +/// Progress information for the task, or null when no task with that ID is tracked. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksGetProgressResult { + /// Progress information for the task, discriminated by type. Returns null when no task with this ID is currently tracked. + pub progress: serde_json::Value, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksGetCurrentPromotableParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// The first sync-waiting task that can currently be promoted to background mode. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksGetCurrentPromotableResult { + /// The first sync-waiting task (agent first, then shell) that can currently be promoted to background mode. Omitted if no such task exists. The returned task is guaranteed to have executionMode='sync' and canPromoteToBackground=true at the time of the call. + #[serde(skip_serializing_if = "Option::is_none")] + pub task: Option, +} + +/// Indicates whether the task was successfully promoted to background mode. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksPromoteToBackgroundResult { + /// Whether the task was successfully promoted to background mode + pub promoted: bool, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksPromoteCurrentToBackgroundParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksPromoteCurrentToBackgroundResult { + /// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. Atomic operation: avoids the race window of getCurrentPromotable + promoteToBackground. + #[serde(skip_serializing_if = "Option::is_none")] + pub task: Option, +} + +/// Indicates whether the background task was successfully cancelled. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksCancelResult { + /// Whether the task was successfully cancelled + pub cancelled: bool, +} + +/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksRemoveResult { + /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). + pub removed: bool, +} + +/// Indicates whether the message was delivered, with an error message when delivery failed. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionTasksSendMessageResult { + /// Error message if delivery failed + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// Whether the message was successfully delivered or steered + pub sent: bool, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsListParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Skills available to the session, with their enabled state. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsListResult { + /// Available skills + pub skills: Vec, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsGetInvokedParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Skills invoked during this session, ordered by invocation time (most recent last). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsGetInvokedResult { + /// Skills invoked during this session, ordered by invocation time (most recent last) + pub skills: Vec, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsReloadParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsReloadResult { + /// Errors emitted while loading skills (e.g. skills that failed to load entirely) + pub errors: Vec, + /// Warnings emitted while loading skills (e.g. skills that loaded but had issues) + pub warnings: Vec, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionSkillsEnsureLoadedParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionMcpListParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// MCP servers configured for the session, with their connection status. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionMcpListResult { + /// Configured MCP servers + pub servers: Vec, } -/// Single-select string field where each option pairs a value with a display label. +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIElicitationStringOneOfField { - /// Default value selected when the form is first shown. - #[serde(skip_serializing_if = "Option::is_none")] - pub default: Option, - /// Help text describing the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub description: Option, - /// Selectable options, each with a value and a display label. - pub one_of: Vec, - /// Human-readable label for the field. - #[serde(skip_serializing_if = "Option::is_none")] - pub title: Option, - /// Type discriminator. Always "string". - pub r#type: UIElicitationStringOneOfFieldType, +pub struct SessionMcpReloadParams { + /// Target session identifier + pub session_id: SessionId, } -/// Pending elicitation request ID and the user's response (accept/decline/cancel + form values). +/// Outcome of an MCP sampling execution: success result, failure error, or cancellation. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UIHandlePendingElicitationRequest { - /// The unique request ID from the elicitation.requested event - pub request_id: RequestId, - /// The elicitation response (accept with form values, decline, or cancel) - pub result: UIElicitationResponse, +pub struct SessionMcpExecuteSamplingResult { + /// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. + pub action: McpSamplingExecutionAction, + /// Error description, present when action='failure'. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, + /// MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. + #[serde(skip_serializing_if = "Option::is_none")] + pub result: Option, } -/// Aggregated code change metrics +/// Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. /// ///
/// @@ -3061,16 +7593,12 @@ pub struct UIHandlePendingElicitationRequest { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsCodeChanges { - /// Number of distinct files modified - pub files_modified_count: i64, - /// Total lines of code added - pub lines_added: i64, - /// Total lines of code removed - pub lines_removed: i64, +pub struct SessionMcpCancelSamplingExecutionResult { + /// True if an in-flight execution with the given requestId was found and signalled to cancel. False when no such execution is in flight (already completed, never started, or cancelled by another caller). + pub cancelled: bool, } -/// Request count and cost metrics for this model +/// Env-value mode recorded on the session after the update. /// ///
/// @@ -3080,14 +7608,12 @@ pub struct UsageMetricsCodeChanges { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsModelMetricRequests { - /// User-initiated premium request cost (with multiplier applied) - pub cost: f64, - /// Number of API requests made with this model - pub count: i64, +pub struct SessionMcpSetEnvValueModeResult { + /// Mode recorded on the session after the update + pub mode: McpSetEnvValueModeDetails, } -/// Schema for the `UsageMetricsModelMetricTokenDetail` type. +/// Identifies the target session. /// ///
/// @@ -3097,12 +7623,12 @@ pub struct UsageMetricsModelMetricRequests { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsModelMetricTokenDetail { - /// Accumulated token count for this token type - pub token_count: i64, +pub struct SessionMcpRemoveGitHubParams { + /// Target session identifier + pub session_id: SessionId, } -/// Token usage metrics for this model +/// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). /// ///
/// @@ -3112,21 +7638,12 @@ pub struct UsageMetricsModelMetricTokenDetail { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsModelMetricUsage { - /// Total tokens read from prompt cache - pub cache_read_tokens: i64, - /// Total tokens written to prompt cache - pub cache_write_tokens: i64, - /// Total input tokens consumed - pub input_tokens: i64, - /// Total output tokens produced - pub output_tokens: i64, - /// Total output tokens used for reasoning - #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning_tokens: Option, +pub struct SessionMcpRemoveGitHubResult { + /// True when the auto-managed `github` MCP server was removed; false when no removal happened (e.g. user has explicitly configured a `github` server, or the server was not registered). + pub removed: bool, } -/// Schema for the `UsageMetricsModelMetric` type. +/// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. /// ///
/// @@ -3136,20 +7653,13 @@ pub struct UsageMetricsModelMetricUsage { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsModelMetric { - /// Request count and cost metrics for this model - pub requests: UsageMetricsModelMetricRequests, - /// Token count details per type - #[serde(default)] - pub token_details: HashMap, - /// Accumulated nano-AI units cost for this model +pub struct SessionMcpOauthLoginResult { + /// URL the caller should open in a browser to complete OAuth. Omitted when cached tokens were still valid and no browser interaction was needed — the server is already reconnected in that case. When present, the runtime starts the callback listener before returning and continues the flow in the background; completion is signaled via session.mcp_server_status_changed. #[serde(skip_serializing_if = "Option::is_none")] - pub total_nano_aiu: Option, - /// Token usage metrics for this model - pub usage: UsageMetricsModelMetricUsage, + pub authorization_url: Option, } -/// Schema for the `UsageMetricsTokenDetail` type. +/// Identifies the target session. /// ///
/// @@ -3159,12 +7669,12 @@ pub struct UsageMetricsModelMetric { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageMetricsTokenDetail { - /// Accumulated token count for this token type - pub token_count: i64, +pub struct SessionPluginsListParams { + /// Target session identifier + pub session_id: SessionId, } -/// Accumulated session usage metrics, including premium request cost, token counts, model breakdown, and code-change totals. +/// Plugins installed for the session, with their enabled state and version metadata. /// ///
/// @@ -3174,452 +7684,331 @@ pub struct UsageMetricsTokenDetail { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct UsageGetMetricsResult { - /// Aggregated code change metrics - pub code_changes: UsageMetricsCodeChanges, - /// Currently active model identifier - #[serde(skip_serializing_if = "Option::is_none")] - pub current_model: Option, - /// Input tokens from the most recent main-agent API call - pub last_call_input_tokens: i64, - /// Output tokens from the most recent main-agent API call - pub last_call_output_tokens: i64, - /// Per-model token and request metrics, keyed by model identifier - pub model_metrics: HashMap, - /// Session start timestamp (epoch milliseconds) - pub session_start_time: i64, - /// Session-wide per-token-type accumulated token counts - #[serde(default)] - pub token_details: HashMap, - /// Total time spent in model API calls (milliseconds) - pub total_api_duration_ms: f64, - /// Session-wide accumulated nano-AI units cost - #[serde(skip_serializing_if = "Option::is_none")] - pub total_nano_aiu: Option, - /// Total user-initiated premium request cost across all models (may be fractional due to multipliers) - pub total_premium_request_cost: f64, - /// Raw count of user-initiated API requests - pub total_user_requests: i64, +pub struct SessionPluginsListResult { + /// Installed plugins + pub plugins: Vec, } -/// Relative path and UTF-8 content for the workspace file to create or overwrite. +/// Indicates whether the session options patch was applied successfully. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesCreateFileRequest { - /// File content to write as a UTF-8 string - pub content: String, - /// Relative path within the workspace files directory - pub path: String, +pub struct SessionOptionsUpdateResult { + /// Whether the operation succeeded + pub success: bool, } +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesGetWorkspaceResultWorkspace { - #[serde(skip_serializing_if = "Option::is_none")] - pub branch: Option, - #[serde( - rename = "chronicle_sync_dismissed", - skip_serializing_if = "Option::is_none" - )] - pub chronicle_sync_dismissed: Option, - #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] - pub created_at: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub cwd: Option, - #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] - pub git_root: Option, - #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] - pub host_type: Option, - pub id: String, - #[serde(rename = "mc_last_event_id", skip_serializing_if = "Option::is_none")] - pub mc_last_event_id: Option, - #[serde(rename = "mc_session_id", skip_serializing_if = "Option::is_none")] - pub mc_session_id: Option, - #[serde(rename = "mc_task_id", skip_serializing_if = "Option::is_none")] - pub mc_task_id: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, - #[serde(rename = "remote_steerable", skip_serializing_if = "Option::is_none")] - pub remote_steerable: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub repository: Option, - #[serde(rename = "summary_count", skip_serializing_if = "Option::is_none")] - pub summary_count: Option, - #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] - pub updated_at: Option, - #[serde(rename = "user_named", skip_serializing_if = "Option::is_none")] - pub user_named: Option, +pub struct SessionExtensionsListParams { + /// Target session identifier + pub session_id: SessionId, } -/// Current workspace metadata for the session, or null when not available. +/// Extensions discovered for the session, with their current status. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesGetWorkspaceResult { - /// Current workspace metadata, or null if not available - pub workspace: Option, +pub struct SessionExtensionsListResult { + /// Discovered extensions and their current status + pub extensions: Vec, } -/// Relative paths of files stored in the session workspace files directory. +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesListFilesResult { - /// Relative file paths in the workspace files directory - pub files: Vec, +pub struct SessionExtensionsReloadParams { + /// Target session identifier + pub session_id: SessionId, } -/// Relative path of the workspace file to read. +/// Indicates whether the external tool call result was handled successfully. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesReadFileRequest { - /// Relative path within the workspace files directory - pub path: String, +pub struct SessionToolsHandlePendingToolCallResult { + /// Whether the tool call result was handled successfully + pub success: bool, } -/// Contents of the requested workspace file as a UTF-8 string. +/// Identifies the target session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct WorkspacesReadFileResult { - /// File content as a UTF-8 string - pub content: String, +pub struct SessionToolsInitializeAndValidateParams { + /// Target session identifier + pub session_id: SessionId, } -/// List of Copilot models available to the resolved user, including capabilities and billing metadata. +/// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ModelsListResult { - /// List of available models with full metadata - pub models: Vec, -} +pub struct SessionToolsInitializeAndValidateResult {} -/// Built-in tools available for the requested model, with their parameters and instructions. +/// Slash commands available in the session, after applying any include/exclude filters. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ToolsListResult { - /// List of available built-in tools with metadata - pub tools: Vec, +pub struct SessionCommandsListResult { + /// Commands available in this session + pub commands: Vec, } -/// User-configured MCP servers, keyed by server name. +/// Indicates whether the pending client-handled command was completed successfully. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct McpConfigListResult { - /// All MCP servers from user config, keyed by name - pub servers: HashMap, +pub struct SessionCommandsHandlePendingCommandResult { + /// Whether the command was handled successfully + pub success: bool, } -/// Skills discovered across global and project sources. +/// Error message produced while executing the command, if any. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SkillsDiscoverResult { - /// All discovered skills across all sources - pub skills: Vec, +pub struct SessionCommandsExecuteResult { + /// Error message produced while executing the command, if any. Omitted when the handler succeeded. + #[serde(skip_serializing_if = "Option::is_none")] + pub error: Option, } -/// Remote session connection result. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Indicates whether the command was accepted into the local execution queue. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionsConnectResult { - /// Metadata for a connected remote session. - pub metadata: ConnectedRemoteSessionMetadata, - /// SDK session ID for the connected remote session. - pub session_id: SessionId, +pub struct SessionCommandsEnqueueResult { + /// True when the command was accepted into the local execution queue. False when the call targets a session that does not support local command queueing (e.g. remote sessions). + pub queued: bool, } -/// Identifies the target session. +/// Indicates whether the queued-command response was matched to a pending request. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionSuspendParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionCommandsRespondToQueuedCommandResult { + /// Whether a pending queued command with the given request ID was found and resolved. False when the request was already resolved, cancelled, or unknown. + pub success: bool, } -/// Identifies the target session. +/// The elicitation response (accept with form values, decline, or cancel) #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAuthGetStatusParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionUiElicitationResult { + /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed) + pub action: UIElicitationResponseAction, + /// The form values submitted by the user (present when action is 'accept') + #[serde(default)] + pub content: HashMap, } -/// Authentication status and account metadata for the session. +/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAuthGetStatusResult { - /// Authentication type - #[serde(skip_serializing_if = "Option::is_none")] - pub auth_type: Option, - /// Copilot plan tier (e.g., individual_pro, business) - #[serde(skip_serializing_if = "Option::is_none")] - pub copilot_plan: Option, - /// Authentication host URL - #[serde(skip_serializing_if = "Option::is_none")] - pub host: Option, - /// Whether the session has resolved authentication - pub is_authenticated: bool, - /// Authenticated login/username, if available - #[serde(skip_serializing_if = "Option::is_none")] - pub login: Option, - /// Human-readable authentication status description - #[serde(skip_serializing_if = "Option::is_none")] - pub status_message: Option, +pub struct SessionUiHandlePendingElicitationResult { + /// Whether the response was accepted. False if the request was already resolved by another client. + pub success: bool, } -/// Identifies the target session. +/// Indicates whether the pending UI request was resolved by this call. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionModelGetCurrentParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionUiHandlePendingUserInputResult { + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + pub success: bool, } -/// The currently selected model for the session. +/// Indicates whether the pending UI request was resolved by this call. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionModelGetCurrentResult { - /// Currently active model identifier - #[serde(skip_serializing_if = "Option::is_none")] - pub model_id: Option, +pub struct SessionUiHandlePendingSamplingResult { + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + pub success: bool, } -/// The model identifier active on the session after the switch. +/// Indicates whether the pending UI request was resolved by this call. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionModelSwitchToResult { - /// Currently active model identifier after the switch - #[serde(skip_serializing_if = "Option::is_none")] - pub model_id: Option, +pub struct SessionUiHandlePendingAutoModeSwitchResult { + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + pub success: bool, } -/// Identifies the target session. +/// Indicates whether the pending UI request was resolved by this call. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionModeGetParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionUiHandlePendingExitPlanModeResult { + /// True if the request was still pending and was resolved by this call. False if the request ID was unknown, already resolved by another client (e.g. GitHub), expired, or otherwise no longer pending. + pub success: bool, } /// Identifies the target session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionNameGetParams { +pub struct SessionUiRegisterDirectAutoModeSwitchHandlerParams { /// Target session identifier pub session_id: SessionId, } -/// The session's friendly name, or null when not yet set. +/// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionNameGetResult { - /// The session name (user-set or auto-generated), or null if not yet set - pub name: Option, +pub struct SessionUiRegisterDirectAutoModeSwitchHandlerResult { + /// Opaque handle representing the registration. Pass this same handle to `unregisterDirectAutoModeSwitchHandler` when the in-process handler is no longer active. Multiple registrations are reference-counted; the server bridge will only dispatch auto-mode-switch requests when no handles are active. + pub handle: String, } -/// Identifies the target session. +/// Indicates whether the handle was active and the registration count was decremented. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionPlanReadParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionUiUnregisterDirectAutoModeSwitchHandlerResult { + /// True if the handle was active and decremented the counter; false if the handle was unknown. + pub unregistered: bool, } -/// Existence, contents, and resolved path of the session plan file. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionPlanReadResult { - /// The content of the plan file, or null if it does not exist - pub content: Option, - /// Whether the plan file exists in the workspace - pub exists: bool, - /// Absolute file path of the plan file, or null if workspace is not enabled - pub path: Option, +pub struct SessionPermissionsConfigureResult { + /// Whether the operation succeeded + pub success: bool, } -/// Identifies the target session. +/// Indicates whether the permission decision was applied; false when the request was already resolved. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionPlanDeleteParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsHandlePendingPermissionRequestResult { + /// Whether the permission request was handled successfully + pub success: bool, } -/// Identifies the target session. +/// List of pending permission requests reconstructed from event history. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesGetWorkspaceParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsPendingRequestsResult { + /// Pending permission prompts reconstructed from the session's event history. Equivalent to the set of `permission.requested` events that have not yet been followed by a matching `permission.completed` event. Used by clients (e.g. the CLI) to hydrate UI for prompts that were emitted before the client attached to the session. + pub items: Vec, } +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesGetWorkspaceResultWorkspace { - #[serde(skip_serializing_if = "Option::is_none")] - pub branch: Option, - #[serde( - rename = "chronicle_sync_dismissed", - skip_serializing_if = "Option::is_none" - )] - pub chronicle_sync_dismissed: Option, - #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] - pub created_at: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub cwd: Option, - #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] - pub git_root: Option, - #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] - pub host_type: Option, - pub id: String, - #[serde(rename = "mc_last_event_id", skip_serializing_if = "Option::is_none")] - pub mc_last_event_id: Option, - #[serde(rename = "mc_session_id", skip_serializing_if = "Option::is_none")] - pub mc_session_id: Option, - #[serde(rename = "mc_task_id", skip_serializing_if = "Option::is_none")] - pub mc_task_id: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub name: Option, - #[serde(rename = "remote_steerable", skip_serializing_if = "Option::is_none")] - pub remote_steerable: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub repository: Option, - #[serde(rename = "summary_count", skip_serializing_if = "Option::is_none")] - pub summary_count: Option, - #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] - pub updated_at: Option, - #[serde(rename = "user_named", skip_serializing_if = "Option::is_none")] - pub user_named: Option, +pub struct SessionPermissionsSetApproveAllResult { + /// Whether the operation succeeded + pub success: bool, } -/// Current workspace metadata for the session, or null when not available. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesGetWorkspaceResult { - /// Current workspace metadata, or null if not available - pub workspace: Option, +pub struct SessionPermissionsModifyRulesResult { + /// Whether the operation succeeded + pub success: bool, } -/// Identifies the target session. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesListFilesParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsSetRequiredResult { + /// Whether the operation succeeded + pub success: bool, } -/// Relative paths of files stored in the session workspace files directory. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesListFilesResult { - /// Relative file paths in the workspace files directory - pub files: Vec, +pub struct SessionPermissionsResetSessionApprovalsResult { + /// Whether the operation succeeded + pub success: bool, } -/// Contents of the requested workspace file as a UTF-8 string. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionWorkspacesReadFileResult { - /// File content as a UTF-8 string - pub content: String, +pub struct SessionPermissionsNotifyPromptShownResult { + /// Whether the operation succeeded + pub success: bool, } -/// Identifies the target session. +/// Snapshot of the session's allow-listed directories and primary working directory. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionInstructionsGetSourcesParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsPathsListResult { + /// All directories currently allowed for tool access on this session. + pub directories: Vec, + /// The primary working directory for this session. + pub primary: String, } -/// Instruction sources loaded for the session, in merge order. +/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionInstructionsGetSourcesResult { - /// Instruction sources for the session - pub sources: Vec, +pub struct SessionPermissionsPathsAddResult { + /// Whether the operation succeeded + pub success: bool, } -/// Indicates whether fleet mode was successfully activated. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionFleetStartResult { - /// Whether fleet mode was successfully activated - pub started: bool, +pub struct SessionPermissionsPathsUpdatePrimaryResult { + /// Whether the operation succeeded + pub success: bool, } -/// Identifies the target session. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Indicates whether the supplied path is within the session's allowed directories. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentListParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsPathsIsPathWithinAllowedDirectoriesResult { + /// Whether the path is within the session's allowed directories + pub allowed: bool, } -/// Custom agents available to the session. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Indicates whether the supplied path is within the session's workspace directory. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentListResult { - /// Available custom agents - pub agents: Vec, +pub struct SessionPermissionsPathsIsPathWithinWorkspaceResult { + /// Whether the path is within the session workspace directory + pub allowed: bool, } -/// Identifies the target session. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Indicates whether the operation succeeded. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentGetCurrentParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionPermissionsUrlsSetUnrestrictedModeResult { + /// Whether the operation succeeded + pub success: bool, } -/// The currently selected custom agent, or null when using the default agent. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Identifier of the session event that was emitted for the log message. #[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionAgentGetCurrentResult { - /// Currently selected custom agent, or null if using the default agent - pub agent: AgentInfo, +#[serde(rename_all = "camelCase")] +pub struct SessionLogResult { + /// The unique identifier of the emitted session event + pub event_id: String, } -/// The newly selected custom agent. +/// Identifies the target session. /// ///
/// @@ -3629,12 +8018,44 @@ pub struct SessionAgentGetCurrentResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentSelectResult { - /// The newly selected custom agent - pub agent: AgentInfo, +pub struct SessionMetadataSnapshotParams { + /// Target session identifier + pub session_id: SessionId, } -/// Identifies the target session. +/// Public-facing projection of workspace metadata for SDK / TUI consumers +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionMetadataSnapshotResultWorkspace { + /// Branch checked out at session start, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub branch: Option, + /// ISO 8601 timestamp when the workspace was created + #[serde(rename = "created_at", skip_serializing_if = "Option::is_none")] + pub created_at: Option, + /// Current working directory at session start + #[serde(skip_serializing_if = "Option::is_none")] + pub cwd: Option, + /// Resolved git root for cwd, if any + #[serde(rename = "git_root", skip_serializing_if = "Option::is_none")] + pub git_root: Option, + /// Repository host type, if known + #[serde(rename = "host_type", skip_serializing_if = "Option::is_none")] + pub host_type: Option, + /// Workspace identifier (1:1 with sessionId) + pub id: String, + /// Display name for the session, if set + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + /// Repository identifier in 'owner/repo' or 'org/project/repo' format, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub repository: Option, + /// ISO 8601 timestamp when the workspace was last updated + #[serde(rename = "updated_at", skip_serializing_if = "Option::is_none")] + pub updated_at: Option, +} + +/// Point-in-time snapshot of slow-changing session identifier and state fields /// ///
/// @@ -3644,9 +8065,37 @@ pub struct SessionAgentSelectResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentDeselectParams { - /// Target session identifier +pub struct SessionMetadataSnapshotResult { + /// True when the session was detected to be in use by another process at construction time. Local consumers may surface a confirmation prompt before fully attaching. Always false for new sessions. + pub already_in_use: bool, + /// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') + pub current_mode: MetadataSnapshotCurrentMode, + /// User-provided name supplied at session construction (via `--name`), if any. Immutable after construction. + #[serde(skip_serializing_if = "Option::is_none")] + pub initial_name: Option, + /// Whether this is a remote session (i.e., one whose runtime executes elsewhere and is steered through this process) + pub is_remote: bool, + /// ISO 8601 timestamp of when the session's persisted state was last modified on disk. For new sessions, equals startTime. For resumed sessions, reflects the previous modification time at construction. + pub modified_time: String, + /// Remote-session-specific metadata. Populated only when `isRemote` is true. Fields are immutable for the lifetime of the session. + #[serde(skip_serializing_if = "Option::is_none")] + pub remote_metadata: Option, + /// Currently selected model identifier, if any + #[serde(skip_serializing_if = "Option::is_none")] + pub selected_model: Option, + /// The unique identifier of the session pub session_id: SessionId, + /// ISO 8601 timestamp of when the session started + pub start_time: String, + /// Short human-readable summary of the session, if known. Omitted when no summary has been generated. + #[serde(skip_serializing_if = "Option::is_none")] + pub summary: Option, + /// Absolute path to the session's current working directory + pub working_directory: String, + /// Public-facing workspace metadata for this session, or null if the session has no associated workspace. Excludes runtime-internal fields (GitHub IDs, summary count, internal flags). + pub workspace: Option, + /// Absolute path to the session's workspace directory on disk, or null if the session has no associated workspace + pub workspace_path: Option, } /// Identifies the target session. @@ -3659,12 +8108,12 @@ pub struct SessionAgentDeselectParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentReloadParams { +pub struct SessionMetadataIsProcessingParams { /// Target session identifier pub session_id: SessionId, } -/// Custom agents available to the session after reloading definitions from disk. +/// Indicates whether the local session is currently processing a turn or background continuation. /// ///
/// @@ -3674,27 +8123,36 @@ pub struct SessionAgentReloadParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionAgentReloadResult { - /// Reloaded custom agents - pub agents: Vec, +pub struct SessionMetadataIsProcessingResult { + /// Whether the session is currently processing user/agent messages. False for non-local sessions (which don't run a local agentic loop). Reflects an in-flight turn or background continuation. + pub processing: bool, } -/// Identifier assigned to the newly started background agent task. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Token-usage breakdown for the session's current context window #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksStartAgentResult { - /// Generated agent ID for the background task - pub agent_id: String, +pub struct SessionMetadataContextInfoResultContextInfo { + /// Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%) + pub buffer_tokens: i64, + /// Token count at which background compaction starts (configurable percentage of promptTokenLimit) + pub compaction_threshold: i64, + /// Tokens consumed by user/assistant/tool messages + pub conversation_tokens: i64, + /// Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. + pub limit: i64, + /// The model used for token counting + pub model_name: String, + /// Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified) + pub prompt_token_limit: i64, + /// Tokens consumed by the system prompt + pub system_tokens: i64, + /// Tokens consumed by tool definitions sent to the model (excludes deferred tools) + pub tool_definitions_tokens: i64, + /// Sum of system, conversation and tool-definition tokens + pub total_tokens: i64, } -/// Identifies the target session. +/// Token breakdown for the session's current context window, or null if uninitialized. /// ///
/// @@ -3704,12 +8162,12 @@ pub struct SessionTasksStartAgentResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksListParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionMetadataContextInfoResult { + /// Token breakdown for the current context window, or null if the session has not yet been initialized (no system prompt or tool metadata cached). + pub context_info: Option, } -/// Background tasks currently tracked by the session. +/// Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). /// ///
/// @@ -3719,12 +8177,9 @@ pub struct SessionTasksListParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksListResult { - /// Currently tracked tasks - pub tasks: Vec, -} +pub struct SessionMetadataRecordContextChangeResult {} -/// Indicates whether the task was successfully promoted to background mode. +/// Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. /// ///
/// @@ -3734,12 +8189,12 @@ pub struct SessionTasksListResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksPromoteToBackgroundResult { - /// Whether the task was successfully promoted to background mode - pub promoted: bool, +pub struct SessionMetadataSetWorkingDirectoryResult { + /// Working directory after the update + pub working_directory: String, } -/// Indicates whether the background task was successfully cancelled. +/// Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. /// ///
/// @@ -3749,27 +8204,32 @@ pub struct SessionTasksPromoteToBackgroundResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksCancelResult { - /// Whether the task was successfully cancelled - pub cancelled: bool, +pub struct SessionMetadataRecomputeContextTokensResult { + /// Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). + pub messages_token_count: i64, + /// Tokens contributed by system/developer prompt snapshots. + pub system_token_count: i64, + /// Sum of tokens across chat-context and system-context messages currently held by the session. + pub total_tokens: i64, } -/// Indicates whether the task was removed. False when the task does not exist or is still running/idle. -/// -///
-/// -/// **Experimental.** This type is part of an experimental wire-protocol surface -/// and may change or be removed in future SDK or CLI releases. -/// -///
+/// Identifier of the spawned process, used to correlate streamed output and exit notifications. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksRemoveResult { - /// Whether the task was removed. Returns false if the task does not exist or is still running/idle (cancel it first). - pub removed: bool, +pub struct SessionShellExecResult { + /// Unique identifier for tracking streamed output + pub process_id: String, } -/// Indicates whether the message was delivered, with an error message when delivery failed. +/// Indicates whether the signal was delivered; false if the process was unknown or already exited. +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionShellKillResult { + /// Whether the signal was sent successfully + pub killed: bool, +} + +/// Identifies the target session. /// ///
/// @@ -3779,15 +8239,12 @@ pub struct SessionTasksRemoveResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionTasksSendMessageResult { - /// Error message if delivery failed - #[serde(skip_serializing_if = "Option::is_none")] - pub error: Option, - /// Whether the message was successfully delivered or steered - pub sent: bool, +pub struct SessionHistoryCompactParams { + /// Target session identifier + pub session_id: SessionId, } -/// Identifies the target session. +/// Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. /// ///
/// @@ -3797,12 +8254,22 @@ pub struct SessionTasksSendMessageResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionSkillsListParams { - /// Target session identifier - pub session_id: SessionId, +pub struct SessionHistoryCompactResult { + /// Post-compaction context window usage breakdown + #[serde(skip_serializing_if = "Option::is_none")] + pub context_window: Option, + /// Number of messages removed during compaction + pub messages_removed: i64, + /// Whether compaction completed successfully + pub success: bool, + /// Summary text produced by compaction. Omitted when compaction did not produce a summary (e.g. failure path). + #[serde(skip_serializing_if = "Option::is_none")] + pub summary_content: Option, + /// Number of tokens freed by compaction + pub tokens_removed: i64, } -/// Skills available to the session, with their enabled state. +/// Number of events that were removed by the truncation. /// ///
/// @@ -3812,9 +8279,9 @@ pub struct SessionSkillsListParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionSkillsListResult { - /// Available skills - pub skills: Vec, +pub struct SessionHistoryTruncateResult { + /// Number of events that were removed + pub events_removed: i64, } /// Identifies the target session. @@ -3827,12 +8294,12 @@ pub struct SessionSkillsListResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionSkillsReloadParams { +pub struct SessionHistoryCancelBackgroundCompactionParams { /// Target session identifier pub session_id: SessionId, } -/// Diagnostics from reloading skill definitions, with warnings and errors as separate lists. +/// Indicates whether an in-progress background compaction was cancelled. /// ///
/// @@ -3842,11 +8309,9 @@ pub struct SessionSkillsReloadParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionSkillsReloadResult { - /// Errors emitted while loading skills (e.g. skills that failed to load entirely) - pub errors: Vec, - /// Warnings emitted while loading skills (e.g. skills that loaded but had issues) - pub warnings: Vec, +pub struct SessionHistoryCancelBackgroundCompactionResult { + /// Whether an in-progress background compaction was cancelled. False when no compaction was running, when the session is remote, or when the underlying processor was unavailable. + pub cancelled: bool, } /// Identifies the target session. @@ -3859,12 +8324,12 @@ pub struct SessionSkillsReloadResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionMcpListParams { +pub struct SessionHistoryAbortManualCompactionParams { /// Target session identifier pub session_id: SessionId, } -/// MCP servers configured for the session, with their connection status. +/// Indicates whether an in-progress manual compaction was aborted. /// ///
/// @@ -3874,9 +8339,9 @@ pub struct SessionMcpListParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionMcpListResult { - /// Configured MCP servers - pub servers: Vec, +pub struct SessionHistoryAbortManualCompactionResult { + /// Whether an in-progress manual compaction was aborted. False when no manual compaction was running, when its abort controller was already aborted, or when the session is remote. + pub aborted: bool, } /// Identifies the target session. @@ -3889,12 +8354,12 @@ pub struct SessionMcpListResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionMcpReloadParams { +pub struct SessionHistorySummarizeForHandoffParams { /// Target session identifier pub session_id: SessionId, } -/// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. +/// Markdown summary of the conversation context (empty when not available). /// ///
/// @@ -3904,10 +8369,9 @@ pub struct SessionMcpReloadParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionMcpOauthLoginResult { - /// URL the caller should open in a browser to complete OAuth. Omitted when cached tokens were still valid and no browser interaction was needed — the server is already reconnected in that case. When present, the runtime starts the callback listener before returning and continues the flow in the background; completion is signaled via session.mcp_server_status_changed. - #[serde(skip_serializing_if = "Option::is_none")] - pub authorization_url: Option, +pub struct SessionHistorySummarizeForHandoffResult { + /// Markdown summary of the conversation context produced by an LLM. Empty string when there are no messages or when the session does not support local summarization. + pub summary: String, } /// Identifies the target session. @@ -3920,12 +8384,12 @@ pub struct SessionMcpOauthLoginResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionPluginsListParams { +pub struct SessionQueuePendingItemsParams { /// Target session identifier pub session_id: SessionId, } -/// Plugins installed for the session, with their enabled state and version metadata. +/// Snapshot of the session's pending queued items and immediate-steering messages. /// ///
/// @@ -3935,9 +8399,11 @@ pub struct SessionPluginsListParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionPluginsListResult { - /// Installed plugins - pub plugins: Vec, +pub struct SessionQueuePendingItemsResult { + /// Pending queued items in submission order. Includes user messages, queued slash commands, and queued model changes; omits internal system items. + pub items: Vec, + /// Display text for messages currently in the immediate steering queue (interjections sent during a running turn). + pub steering_messages: Vec, } /// Identifies the target session. @@ -3950,12 +8416,12 @@ pub struct SessionPluginsListResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionExtensionsListParams { +pub struct SessionQueueRemoveMostRecentParams { /// Target session identifier pub session_id: SessionId, } -/// Extensions discovered for the session, with their current status. +/// Indicates whether a user-facing pending item was removed. /// ///
/// @@ -3965,9 +8431,9 @@ pub struct SessionExtensionsListParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionExtensionsListResult { - /// Discovered extensions and their current status - pub extensions: Vec, +pub struct SessionQueueRemoveMostRecentResult { + /// True if a user-facing pending item was removed (LIFO across both queues); false when no removable items remained. + pub removed: bool, } /// Identifies the target session. @@ -3980,108 +8446,30 @@ pub struct SessionExtensionsListResult { /// #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionExtensionsReloadParams { +pub struct SessionQueueClearParams { /// Target session identifier pub session_id: SessionId, } -/// Indicates whether the external tool call result was handled successfully. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionToolsHandlePendingToolCallResult { - /// Whether the tool call result was handled successfully - pub success: bool, -} - -/// Slash commands available in the session, after applying any include/exclude filters. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionCommandsListResult { - /// Commands available in this session - pub commands: Vec, -} - -/// Indicates whether the pending client-handled command was completed successfully. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionCommandsHandlePendingCommandResult { - /// Whether the command was handled successfully - pub success: bool, -} - -/// Indicates whether the queued-command response was accepted by the session. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionCommandsRespondToQueuedCommandResult { - /// Whether the response was accepted (false if the requestId was not found or already resolved) - pub success: bool, -} - -/// The elicitation response (accept with form values, decline, or cancel) -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionUiElicitationResult { - /// The user's response: accept (submitted), decline (rejected), or cancel (dismissed) - pub action: UIElicitationResponseAction, - /// The form values submitted by the user (present when action is 'accept') - #[serde(default)] - pub content: HashMap, -} - -/// Indicates whether the elicitation response was accepted; false if it was already resolved by another client. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionUiHandlePendingElicitationResult { - /// Whether the response was accepted. False if the request was already resolved by another client. - pub success: bool, -} - -/// Indicates whether the permission decision was applied; false when the request was already resolved. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionPermissionsHandlePendingPermissionRequestResult { - /// Whether the permission request was handled successfully - pub success: bool, -} - -/// Indicates whether the operation succeeded. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionPermissionsSetApproveAllResult { - /// Whether the operation succeeded - pub success: bool, -} - -/// Indicates whether the operation succeeded. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionPermissionsResetSessionApprovalsResult { - /// Whether the operation succeeded - pub success: bool, -} - -/// Identifier of the session event that was emitted for the log message. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionLogResult { - /// The unique identifier of the emitted session event - pub event_id: String, -} - -/// Identifier of the spawned process, used to correlate streamed output and exit notifications. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SessionShellExecResult { - /// Unique identifier for tracking streamed output - pub process_id: String, -} - -/// Indicates whether the signal was delivered; false if the process was unknown or already exited. +/// Batch of session events returned by a read, with cursor and continuation metadata. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionShellKillResult { - /// Whether the signal was sent successfully - pub killed: bool, +pub struct SessionEventLogReadResult { + /// Opaque cursor for the next read. Pass back unchanged in the next read.cursor to continue from where this read left off. Always present, even when no events were returned. + pub cursor: String, + /// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. + pub cursor_status: EventsCursorStatus, + /// Events are delivered in two batches per read: persisted events first (in append order), then ephemeral events (in seq order). When `waitMs > 0` and the catch-up batches were empty, post-wait events follow the same two-batch ordering. Persisted and ephemeral events do not interleave within a single read. + pub events: Vec, + /// True when the read returned `max` events and more events are available immediately. When false, the next read with a non-zero `waitMs` will block until a new event arrives or the wait expires. + pub has_more: bool, } /// Identifies the target session. @@ -4094,12 +8482,12 @@ pub struct SessionShellKillResult { /// #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionHistoryCompactParams { +pub struct SessionEventLogTailParams { /// Target session identifier pub session_id: SessionId, } -/// Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. +/// Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). /// ///
/// @@ -4109,19 +8497,12 @@ pub struct SessionHistoryCompactParams { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionHistoryCompactResult { - /// Post-compaction context window usage breakdown - #[serde(skip_serializing_if = "Option::is_none")] - pub context_window: Option, - /// Number of messages removed during compaction - pub messages_removed: i64, - /// Whether compaction completed successfully - pub success: bool, - /// Number of tokens freed by compaction - pub tokens_removed: i64, +pub struct SessionEventLogTailResult { + /// Opaque cursor pointing at the current tail of the session's persisted-events history. Pass back to `read` to receive only events that arrive AFTER this snapshot. When the session has no events, this returns the same sentinel as an unset cursor (i.e. equivalent to omitting the cursor on a first read). + pub cursor: String, } -/// Number of events that were removed by the truncation. +/// Opaque handle representing an event-type interest registration. /// ///
/// @@ -4131,9 +8512,24 @@ pub struct SessionHistoryCompactResult { ///
#[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SessionHistoryTruncateResult { - /// Number of events that were removed - pub events_removed: i64, +pub struct SessionEventLogRegisterInterestResult { + /// Opaque handle for this registration. Pass to releaseInterest to release. Each call to registerInterest produces a fresh handle, even when the same eventType is registered multiple times. + pub handle: String, +} + +/// Indicates whether the operation succeeded. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionEventLogReleaseInterestResult { + /// Whether the operation succeeded + pub success: bool, } /// Identifies the target session. @@ -4173,13 +8569,13 @@ pub struct SessionUsageGetMetricsResult { pub last_call_output_tokens: i64, /// Per-model token and request metrics, keyed by model identifier pub model_metrics: HashMap, - /// Session start timestamp (epoch milliseconds) - pub session_start_time: i64, + /// ISO 8601 timestamp when the session started + pub session_start_time: String, /// Session-wide per-token-type accumulated token counts #[serde(default)] pub token_details: HashMap, /// Total time spent in model API calls (milliseconds) - pub total_api_duration_ms: f64, + pub total_api_duration_ms: i64, /// Session-wide accumulated nano-AI units cost #[serde(skip_serializing_if = "Option::is_none")] pub total_nano_aiu: Option, @@ -4222,6 +8618,64 @@ pub struct SessionRemoteDisableParams { pub session_id: SessionId, } +/// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionRemoteNotifySteerableChangedResult {} + +/// Identifies the target session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionScheduleListParams { + /// Target session identifier + pub session_id: SessionId, +} + +/// Snapshot of the currently active recurring prompts for this session. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionScheduleListResult { + /// Active scheduled prompts, ordered by id. + pub entries: Vec, +} + +/// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SessionScheduleStopResult { + /// The removed entry, or omitted if no entry matched. + #[serde(skip_serializing_if = "Option::is_none")] + pub entry: Option, +} + /// Identifies the target session. #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -4230,6 +8684,42 @@ pub struct SessionFsSqliteExistsParams { pub session_id: SessionId, } +/// Where the agent definition was loaded from +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum AgentInfoSource { + #[serde(rename = "user")] + User, + #[serde(rename = "project")] + Project, + #[serde(rename = "inherited")] + Inherited, + #[serde(rename = "remote")] + Remote, + #[serde(rename = "plugin")] + Plugin, + #[serde(rename = "builtin")] + Builtin, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style). +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum ApiKeyAuthInfoType { + #[serde(rename = "api-key")] + #[default] + ApiKey, +} + /// Authentication type #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum AuthInfoType { @@ -4314,6 +8804,22 @@ pub enum ContentFilterMode { Unknown, } +/// Authentication host (always the public GitHub host). +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum CopilotApiTokenAuthInfoHost { + #[serde(rename = "https://github.com")] + #[default] + HttpsGithubCom, +} + +/// Direct Copilot API authentication via the `GITHUB_COPILOT_API_TOKEN` + `COPILOT_API_URL` environment-variable pair. The token itself is read from the environment by the runtime, not carried in this struct. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum CopilotApiTokenAuthInfoType { + #[serde(rename = "copilot-api-token")] + #[default] + CopilotApiToken, +} + /// Server transport type: stdio, http, sse, or memory #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum DiscoveredMcpServerType { @@ -4331,6 +8837,54 @@ pub enum DiscoveredMcpServerType { Unknown, } +/// Personal access token (PAT) or server-to-server token sourced from an environment variable. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum EnvAuthInfoType { + #[serde(rename = "env")] + #[default] + Env, +} + +/// Agent-scope filter: 'primary' returns only main-agent events plus events whose type starts with 'subagent.' (matching the typed-subscription default behavior); 'all' returns events from all agents (matching wildcard-subscription behavior). Default is 'all' to preserve wildcard semantics for catch-up callers. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum EventsAgentScope { + #[serde(rename = "primary")] + Primary, + #[serde(rename = "all")] + All, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Cursor status: 'ok' means the cursor was applied successfully; 'expired' means the cursor referred to an event that no longer exists in history (e.g. truncated or compacted away) and the read started from the beginning of the remaining history. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum EventsCursorStatus { + #[serde(rename = "ok")] + Ok, + #[serde(rename = "expired")] + Expired, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + /// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/) /// ///
@@ -4449,6 +9003,54 @@ pub enum ExternalToolTextResultForLlmContentTextType { Text, } +/// Authentication via the `gh` CLI's saved credentials. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum GhCliAuthInfoType { + #[serde(rename = "gh-cli")] + #[default] + GhCli, +} + +/// Authentication host. HMAC auth always targets the public GitHub host. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum HMACAuthInfoHost { + #[serde(rename = "https://github.com")] + #[default] + HttpsGithubCom, +} + +/// HMAC-based authentication used by GitHub-internal services. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum HMACAuthInfoType { + #[serde(rename = "hmac")] + #[default] + Hmac, +} + +/// Constant value. Always "github". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum InstalledPluginSourceGithubSource { + #[serde(rename = "github")] + #[default] + Github, +} + +/// Constant value. Always "local". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum InstalledPluginSourceLocalSource { + #[serde(rename = "local")] + #[default] + Local, +} + +/// Constant value. Always "url". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum InstalledPluginSourceUrlSource { + #[serde(rename = "url")] + #[default] + Url, +} + /// Where this source lives — used for UI grouping #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum InstructionsSourcesLocation { @@ -4458,6 +9060,8 @@ pub enum InstructionsSourcesLocation { Repository, #[serde(rename = "working-directory")] WorkingDirectory, + #[serde(rename = "plugin")] + Plugin, /// Unknown variant for forward compatibility. #[default] #[serde(other)] @@ -4479,6 +9083,8 @@ pub enum InstructionsSourcesType { NestedAgents, #[serde(rename = "child-instructions")] ChildInstructions, + #[serde(rename = "plugin")] + Plugin, /// Unknown variant for forward compatibility. #[default] #[serde(other)] @@ -4500,26 +9106,130 @@ pub enum SessionLogLevel { Unknown, } -/// OAuth grant type to use when authenticating to the remote MCP server. +/// Outcome of the sampling inference. 'success' produced a response; 'failure' encountered an error (including agent-side rejection by content filter or criteria); 'cancelled' the caller cancelled this execution via cancelSamplingExecution. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum McpSamplingExecutionAction { + #[serde(rename = "success")] + Success, + #[serde(rename = "failure")] + Failure, + #[serde(rename = "cancelled")] + Cancelled, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// OAuth grant type to use when authenticating to the remote MCP server. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum McpServerConfigHttpOauthGrantType { + #[serde(rename = "authorization_code")] + AuthorizationCode, + #[serde(rename = "client_credentials")] + ClientCredentials, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Remote transport type. Defaults to "http" when omitted. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum McpServerConfigHttpType { + #[serde(rename = "http")] + Http, + #[serde(rename = "sse")] + Sse, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// How environment-variable values supplied to MCP servers are resolved. "direct" passes literal string values; "indirect" treats values as references (e.g. names of environment variables on the host) that the runtime resolves before launch. Defaults to the runtime's startup mode; clients that intentionally launch MCP servers with literal values (e.g. CLI prompt mode and ACP) set this to "direct". +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum McpSetEnvValueModeDetails { + #[serde(rename = "direct")] + Direct, + #[serde(rename = "indirect")] + Indirect, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Hosting platform type of the repository +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionWorkingDirectoryContextHostType { + #[serde(rename = "github")] + Github, + #[serde(rename = "ado")] + Ado, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// The current agent mode for this session (e.g., 'interactive', 'plan', 'autopilot') +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] -pub enum McpServerConfigHttpOauthGrantType { - #[serde(rename = "authorization_code")] - AuthorizationCode, - #[serde(rename = "client_credentials")] - ClientCredentials, +pub enum MetadataSnapshotCurrentMode { + #[serde(rename = "interactive")] + Interactive, + #[serde(rename = "plan")] + Plan, + #[serde(rename = "autopilot")] + Autopilot, /// Unknown variant for forward compatibility. #[default] #[serde(other)] Unknown, } -/// Remote transport type. Defaults to "http" when omitted. +/// Whether the remote task originated from Copilot Coding Agent (cca) or a CLI `--remote` invocation. +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] -pub enum McpServerConfigHttpType { - #[serde(rename = "http")] - Http, - #[serde(rename = "sse")] - Sse, +pub enum MetadataSnapshotRemoteMetadataTaskType { + #[serde(rename = "cca")] + Cca, + #[serde(rename = "cli")] + Cli, /// Unknown variant for forward compatibility. #[default] #[serde(other)] @@ -4573,7 +9283,27 @@ pub enum ModelPolicyState { Unknown, } -/// The permission request was approved for this one instance +/// How env values are passed to MCP servers (`direct` inlines literal values; `indirect` resolves at launch). +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum OptionsUpdateEnvValueMode { + #[serde(rename = "direct")] + Direct, + #[serde(rename = "indirect")] + Indirect, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Approve this single request only #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionApproveOnceKind { #[serde(rename = "approve-once")] @@ -4653,7 +9383,7 @@ pub enum PermissionDecisionApproveForSessionApprovalExtensionPermissionAccessKin ExtensionPermissionAccess, } -/// The approval to add as a session-scoped rule +/// Session-scoped approval to remember (tool prompts only; omitted for path/url prompts) #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum PermissionDecisionApproveForSessionApproval { @@ -4668,7 +9398,7 @@ pub enum PermissionDecisionApproveForSessionApproval { ExtensionPermissionAccess(PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess), } -/// Approved and remembered for the rest of the session +/// Approve and remember for the rest of the session #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionApproveForSessionKind { #[serde(rename = "approve-for-session")] @@ -4748,7 +9478,7 @@ pub enum PermissionDecisionApproveForLocationApprovalExtensionPermissionAccessKi ExtensionPermissionAccess, } -/// The approval to persist for this location +/// Approval to persist for this location #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum PermissionDecisionApproveForLocationApproval { @@ -4765,7 +9495,7 @@ pub enum PermissionDecisionApproveForLocationApproval { ), } -/// Approved and persisted for this project location +/// Approve and persist for this project location #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionApproveForLocationKind { #[serde(rename = "approve-for-location")] @@ -4773,7 +9503,7 @@ pub enum PermissionDecisionApproveForLocationKind { ApproveForLocation, } -/// Approved and persisted across sessions +/// Approve and persist across sessions (URL prompts only) #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionApprovePermanentlyKind { #[serde(rename = "approve-permanently")] @@ -4781,7 +9511,7 @@ pub enum PermissionDecisionApprovePermanentlyKind { ApprovePermanently, } -/// Denied by the user during an interactive prompt +/// Reject the request #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionRejectKind { #[serde(rename = "reject")] @@ -4789,7 +9519,7 @@ pub enum PermissionDecisionRejectKind { Reject, } -/// Denied because user confirmation was unavailable +/// No user is available to confirm the request #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum PermissionDecisionUserNotAvailableKind { #[serde(rename = "user-not-available")] @@ -4797,7 +9527,79 @@ pub enum PermissionDecisionUserNotAvailableKind { UserNotAvailable, } -/// Decision to apply to a pending permission request. +/// The permission request was approved +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionApprovedKind { + #[serde(rename = "approved")] + #[default] + Approved, +} + +/// Approved and remembered for the rest of the session +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionApprovedForSessionKind { + #[serde(rename = "approved-for-session")] + #[default] + ApprovedForSession, +} + +/// Approved and persisted for this project location +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionApprovedForLocationKind { + #[serde(rename = "approved-for-location")] + #[default] + ApprovedForLocation, +} + +/// The permission request was cancelled before a response was used +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionCancelledKind { + #[serde(rename = "cancelled")] + #[default] + Cancelled, +} + +/// Denied because approval rules explicitly blocked it +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionDeniedByRulesKind { + #[serde(rename = "denied-by-rules")] + #[default] + DeniedByRules, +} + +/// Denied because no approval rule matched and user confirmation was unavailable +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUserKind { + #[serde(rename = "denied-no-approval-rule-and-could-not-request-from-user")] + #[default] + DeniedNoApprovalRuleAndCouldNotRequestFromUser, +} + +/// Denied by the user during an interactive prompt +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionDeniedInteractivelyByUserKind { + #[serde(rename = "denied-interactively-by-user")] + #[default] + DeniedInteractivelyByUser, +} + +/// Denied by the organization's content exclusion policy +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionDeniedByContentExclusionPolicyKind { + #[serde(rename = "denied-by-content-exclusion-policy")] + #[default] + DeniedByContentExclusionPolicy, +} + +/// Denied by a permission request hook registered by an extension or plugin +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionDecisionDeniedByPermissionRequestHookKind { + #[serde(rename = "denied-by-permission-request-hook")] + #[default] + DeniedByPermissionRequestHook, +} + +/// The client's response to the pending permission prompt #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum PermissionDecision { @@ -4807,6 +9609,80 @@ pub enum PermissionDecision { ApprovePermanently(PermissionDecisionApprovePermanently), Reject(PermissionDecisionReject), UserNotAvailable(PermissionDecisionUserNotAvailable), + Approved(PermissionDecisionApproved), + ApprovedForSession(PermissionDecisionApprovedForSession), + ApprovedForLocation(PermissionDecisionApprovedForLocation), + Cancelled(PermissionDecisionCancelled), + DeniedByRules(PermissionDecisionDeniedByRules), + DeniedNoApprovalRuleAndCouldNotRequestFromUser( + PermissionDecisionDeniedNoApprovalRuleAndCouldNotRequestFromUser, + ), + DeniedInteractivelyByUser(PermissionDecisionDeniedInteractivelyByUser), + DeniedByContentExclusionPolicy(PermissionDecisionDeniedByContentExclusionPolicy), + DeniedByPermissionRequestHook(PermissionDecisionDeniedByPermissionRequestHook), +} + +/// Allowed values for the `PermissionsConfigureAdditionalContentExclusionPolicyScope` enumeration. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionsConfigureAdditionalContentExclusionPolicyScope { + #[serde(rename = "repo")] + Repo, + #[serde(rename = "all")] + All, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Whether the change applies to ephemeral session-scoped rules (cleared at session end) or to location-scoped rules persisted via the location-permissions config file. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionsModifyRulesScope { + #[serde(rename = "session")] + Session, + #[serde(rename = "location")] + Location, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Optional source for allow-all telemetry. Defaults to `rpc` when omitted for SDK callers. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum PermissionsSetApproveAllSource { + #[serde(rename = "cli_flag")] + CliFlag, + #[serde(rename = "slash_command")] + SlashCommand, + #[serde(rename = "autopilot_confirmation")] + AutopilotConfirmation, + #[serde(rename = "rpc")] + Rpc, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Whether this item is a queued user message or a queued slash command / model change +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum QueuePendingItemsKind { + #[serde(rename = "message")] + Message, + #[serde(rename = "command")] + Command, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, } /// Per-session remote mode. "off" disables remote, "export" exports session events to GitHub without enabling remote steering, "on" enables both export and remote steering. @@ -4831,6 +9707,103 @@ pub enum RemoteSessionMode { Unknown, } +/// The UI mode the agent was in when this message was sent. Defaults to the session's current mode. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAgentMode { + #[serde(rename = "interactive")] + Interactive, + #[serde(rename = "plan")] + Plan, + #[serde(rename = "autopilot")] + Autopilot, + #[serde(rename = "shell")] + Shell, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Attachment type discriminator +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAttachmentBlobType { + #[serde(rename = "blob")] + #[default] + Blob, +} + +/// Attachment type discriminator +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAttachmentDirectoryType { + #[serde(rename = "directory")] + #[default] + Directory, +} + +/// Attachment type discriminator +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAttachmentFileType { + #[serde(rename = "file")] + #[default] + File, +} + +/// Type of GitHub reference +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAttachmentGithubReferenceType { + #[serde(rename = "issue")] + Issue, + #[serde(rename = "pr")] + Pr, + #[serde(rename = "discussion")] + Discussion, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Attachment type discriminator +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendAttachmentSelectionType { + #[serde(rename = "selection")] + #[default] + Selection, +} + +/// How to deliver the message. `enqueue` (default) appends to the message queue. `immediate` interjects during an in-progress turn. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SendMode { + #[serde(rename = "enqueue")] + Enqueue, + #[serde(rename = "immediate")] + Immediate, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// Repository host type +/// +///
+/// +/// **Experimental.** This type is part of an experimental wire-protocol surface +/// and may change or be removed in future SDK or CLI releases. +/// +///
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionContextHostType { + #[serde(rename = "github")] + Github, + #[serde(rename = "ado")] + Ado, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + /// Error classification #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum SessionFsErrorCode { @@ -4883,6 +9856,43 @@ pub enum SessionFsSqliteQueryType { Unknown, } +/// Constant value. Always "github". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionInstalledPluginSourceGithubSource { + #[serde(rename = "github")] + #[default] + Github, +} + +/// Constant value. Always "local". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionInstalledPluginSourceLocalSource { + #[serde(rename = "local")] + #[default] + Local, +} + +/// Constant value. Always "url". +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionInstalledPluginSourceUrlSource { + #[serde(rename = "url")] + #[default] + Url, +} + +/// Repository host type, if known +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionMetadataSnapshotWorkspaceHostType { + #[serde(rename = "github")] + Github, + #[serde(rename = "ado")] + Ado, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + /// Signal to send (default: SIGTERM) #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum ShellKillSignal { @@ -5010,6 +10020,29 @@ pub enum TaskShellInfoType { Shell, } +/// SDK-side token authentication; the host configured the token directly via the SDK. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum TokenAuthInfoType { + #[serde(rename = "token")] + #[default] + Token, +} + +/// User's choice for auto-mode switching: yes (allow this turn), yes_always (allow + persist as setting), or no (decline). +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum UIAutoModeSwitchResponse { + #[serde(rename = "yes")] + Yes, + #[serde(rename = "yes_always")] + YesAlways, + #[serde(rename = "no")] + No, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + /// Type discriminator. Always "array". #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum UIElicitationArrayAnyOfFieldType { @@ -5119,6 +10152,31 @@ pub enum UIElicitationStringOneOfFieldType { String, } +/// The action the user selected. Defaults to 'autopilot' when autoApproveEdits is true, otherwise 'interactive'. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum UIExitPlanModeAction { + #[serde(rename = "exit_only")] + ExitOnly, + #[serde(rename = "interactive")] + Interactive, + #[serde(rename = "autopilot")] + Autopilot, + #[serde(rename = "autopilot_fleet")] + AutopilotFleet, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + +/// OAuth user authentication. The token itself is held in the runtime's secret token store (keyed by host+login) and is NOT carried in this struct. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum UserAuthInfoType { + #[serde(rename = "user")] + #[default] + User, +} + #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum WorkspacesGetWorkspaceResultWorkspaceHostType { #[serde(rename = "github")] @@ -5131,6 +10189,19 @@ pub enum WorkspacesGetWorkspaceResultWorkspaceHostType { Unknown, } +/// Repository host type, if known +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum WorkspaceSummaryHostType { + #[serde(rename = "github")] + Github, + #[serde(rename = "ado")] + Ado, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} + #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum SessionWorkspacesGetWorkspaceResultWorkspaceHostType { #[serde(rename = "github")] @@ -5142,3 +10213,16 @@ pub enum SessionWorkspacesGetWorkspaceResultWorkspaceHostType { #[serde(other)] Unknown, } + +/// Repository host type, if known +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum SessionMetadataSnapshotResultWorkspaceHostType { + #[serde(rename = "github")] + Github, + #[serde(rename = "ado")] + Ado, + /// Unknown variant for forward compatibility. + #[default] + #[serde(other)] + Unknown, +} diff --git a/rust/src/generated/rpc.rs b/rust/src/generated/rpc.rs index dac970fd4..2d18b816b 100644 --- a/rust/src/generated/rpc.rs +++ b/rust/src/generated/rpc.rs @@ -79,7 +79,7 @@ impl<'a> ClientRpc<'a> { /// /// # Returns /// - /// Server liveness response, including the echoed message, current timestamp, and protocol version. + /// Server liveness response, including the echoed message, current server timestamp, and protocol version. pub async fn ping(&self, params: PingRequest) -> Result { let wire_params = serde_json::to_value(params)?; let _value = self @@ -436,312 +436,2108 @@ impl<'a> ClientRpcSessions<'a> { .await?; Ok(serde_json::from_value(_value)?) } -} - -/// `skills.*` RPCs. -#[derive(Clone, Copy)] -pub struct ClientRpcSkills<'a> { - pub(crate) client: &'a Client, -} -impl<'a> ClientRpcSkills<'a> { - /// `skills.config.*` sub-namespace. - pub fn config(&self) -> ClientRpcSkillsConfig<'a> { - ClientRpcSkillsConfig { - client: self.client, - } + /// Lists persisted sessions, optionally filtered by working-directory context. + /// + /// Wire method: `sessions.list`. + /// + /// # Returns + /// + /// Persisted sessions matching the filter, ordered most-recently-modified first. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({}); + let _value = self + .client + .call(rpc_methods::SESSIONS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// Discovers skills across global and project sources. + /// Lists persisted sessions, optionally filtered by working-directory context. /// - /// Wire method: `skills.discover`. + /// Wire method: `sessions.list`. /// /// # Parameters /// - /// * `params` - Optional project paths and additional skill directories to include in discovery. + /// * `params` - Optional metadata-load limit and context filter applied to the returned sessions. /// /// # Returns /// - /// Skills discovered across global and project sources. - pub async fn discover(&self, params: SkillsDiscoverRequest) -> Result { + /// Persisted sessions matching the filter, ordered most-recently-modified first. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list_with_params( + &self, + params: SessionsListRequest, + ) -> Result { let wire_params = serde_json::to_value(params)?; let _value = self .client - .call(rpc_methods::SKILLS_DISCOVER, Some(wire_params)) + .call(rpc_methods::SESSIONS_LIST, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } -} - -/// `skills.config.*` RPCs. -#[derive(Clone, Copy)] -pub struct ClientRpcSkillsConfig<'a> { - pub(crate) client: &'a Client, -} -impl<'a> ClientRpcSkillsConfig<'a> { - /// Replaces the global list of disabled skills. + /// Finds the local session bound to a GitHub task ID, if any. /// - /// Wire method: `skills.config.setDisabledSkills`. + /// Wire method: `sessions.findByTaskId`. /// /// # Parameters /// - /// * `params` - Skill names to mark as disabled in global configuration, replacing any previous list. - pub async fn set_disabled_skills( + /// * `params` - GitHub task ID to look up. + /// + /// # Returns + /// + /// ID of the local session bound to the given GitHub task, or omitted when none. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn find_by_task_id( &self, - params: SkillsConfigSetDisabledSkillsRequest, - ) -> Result<(), Error> { + params: SessionsFindByTaskIDRequest, + ) -> Result { let wire_params = serde_json::to_value(params)?; let _value = self .client - .call( - rpc_methods::SKILLS_CONFIG_SETDISABLEDSKILLS, - Some(wire_params), - ) + .call(rpc_methods::SESSIONS_FINDBYTASKID, Some(wire_params)) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } -} - -/// `tools.*` RPCs. -#[derive(Clone, Copy)] -pub struct ClientRpcTools<'a> { - pub(crate) client: &'a Client, -} -impl<'a> ClientRpcTools<'a> { - /// Lists built-in tools available for a model. + /// Resolves a UUID prefix to a unique session ID, if exactly one session matches. /// - /// Wire method: `tools.list`. + /// Wire method: `sessions.findByPrefix`. /// /// # Parameters /// - /// * `params` - Optional model identifier whose tool overrides should be applied to the listing. + /// * `params` - UUID prefix to resolve to a unique session ID. /// /// # Returns /// - /// Built-in tools available for the requested model, with their parameters and instructions. - pub async fn list(&self, params: ToolsListRequest) -> Result { + /// Session ID matching the prefix, omitted when no unique match exists. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn find_by_prefix( + &self, + params: SessionsFindByPrefixRequest, + ) -> Result { let wire_params = serde_json::to_value(params)?; let _value = self .client - .call(rpc_methods::TOOLS_LIST, Some(wire_params)) + .call(rpc_methods::SESSIONS_FINDBYPREFIX, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } -} - -/// Typed view over a [`Session`]'s RPC namespace. -#[derive(Clone, Copy)] -pub struct SessionRpc<'a> { - pub(crate) session: &'a Session, -} - -impl<'a> SessionRpc<'a> { - /// `session.agent.*` sub-namespace. - pub fn agent(&self) -> SessionRpcAgent<'a> { - SessionRpcAgent { - session: self.session, - } - } - - /// `session.auth.*` sub-namespace. - pub fn auth(&self) -> SessionRpcAuth<'a> { - SessionRpcAuth { - session: self.session, - } - } - /// `session.commands.*` sub-namespace. - pub fn commands(&self) -> SessionRpcCommands<'a> { - SessionRpcCommands { - session: self.session, - } + /// Returns the most-relevant prior session for a given working-directory context. + /// + /// Wire method: `sessions.getLastForContext`. + /// + /// # Parameters + /// + /// * `params` - Optional working-directory context used to score session relevance. + /// + /// # Returns + /// + /// Most-relevant session ID for the supplied context, or omitted when no sessions exist. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_last_for_context( + &self, + params: SessionsGetLastForContextRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_GETLASTFORCONTEXT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.extensions.*` sub-namespace. - pub fn extensions(&self) -> SessionRpcExtensions<'a> { - SessionRpcExtensions { - session: self.session, - } + /// Computes the absolute path to a session's persisted events.jsonl file. + /// + /// Wire method: `sessions.getEventFilePath`. + /// + /// # Parameters + /// + /// * `params` - Session ID whose event-log file path to compute. + /// + /// # Returns + /// + /// Absolute path to the session's events.jsonl file on disk. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_event_file_path( + &self, + params: SessionsGetEventFilePathRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_GETEVENTFILEPATH, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.fleet.*` sub-namespace. - pub fn fleet(&self) -> SessionRpcFleet<'a> { - SessionRpcFleet { - session: self.session, - } + /// Returns the on-disk byte size of each session's workspace directory. + /// + /// Wire method: `sessions.getSizes`. + /// + /// # Returns + /// + /// Map of sessionId -> on-disk size in bytes for each session's workspace directory. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_sizes(&self) -> Result { + let wire_params = serde_json::json!({}); + let _value = self + .client + .call(rpc_methods::SESSIONS_GETSIZES, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.history.*` sub-namespace. - pub fn history(&self) -> SessionRpcHistory<'a> { - SessionRpcHistory { - session: self.session, - } + /// Returns the subset of the supplied session IDs that are currently held by another running process. + /// + /// Wire method: `sessions.checkInUse`. + /// + /// # Parameters + /// + /// * `params` - Session IDs to test for live in-use locks. + /// + /// # Returns + /// + /// Session IDs from the input set that are currently in use by another process. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn check_in_use( + &self, + params: SessionsCheckInUseRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_CHECKINUSE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.instructions.*` sub-namespace. - pub fn instructions(&self) -> SessionRpcInstructions<'a> { - SessionRpcInstructions { - session: self.session, - } + /// Returns a session's persisted remote-steerable flag, if any has been recorded. + /// + /// Wire method: `sessions.getPersistedRemoteSteerable`. + /// + /// # Parameters + /// + /// * `params` - Session ID to look up the persisted remote-steerable flag for. + /// + /// # Returns + /// + /// The session's persisted remote-steerable flag, or omitted when no value has been persisted. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_persisted_remote_steerable( + &self, + params: SessionsGetPersistedRemoteSteerableRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call( + rpc_methods::SESSIONS_GETPERSISTEDREMOTESTEERABLE, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.mcp.*` sub-namespace. - pub fn mcp(&self) -> SessionRpcMcp<'a> { - SessionRpcMcp { - session: self.session, - } + /// Closes a session: emits shutdown, flushes pending events, releases the in-use lock, and disposes the active session. + /// + /// Wire method: `sessions.close`. + /// + /// # Parameters + /// + /// * `params` - Session ID to close. + /// + /// # Returns + /// + /// Closes a session: emits shutdown, flushes pending events to disk, releases the in-use lock, disposes the active session. Idempotent: succeeds even if the session is not currently active. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn close(&self, params: SessionsCloseRequest) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_CLOSE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.mode.*` sub-namespace. - pub fn mode(&self) -> SessionRpcMode<'a> { - SessionRpcMode { - session: self.session, - } + /// Closes, deactivates, and deletes a set of sessions, returning the bytes freed per session. + /// + /// Wire method: `sessions.bulkDelete`. + /// + /// # Parameters + /// + /// * `params` - Session IDs to close, deactivate, and delete from disk. + /// + /// # Returns + /// + /// Map of sessionId -> bytes freed by removing the session's workspace directory. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn bulk_delete( + &self, + params: SessionsBulkDeleteRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_BULKDELETE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.model.*` sub-namespace. - pub fn model(&self) -> SessionRpcModel<'a> { - SessionRpcModel { - session: self.session, - } + /// Deletes sessions older than the given threshold, with optional dry-run and exclusion list. + /// + /// Wire method: `sessions.pruneOld`. + /// + /// # Parameters + /// + /// * `params` - Age threshold and optional flags controlling which old sessions are pruned (or simulated when dryRun is true). + /// + /// # Returns + /// + /// Outcome of the prune operation: deleted IDs, dry-run candidates, skipped IDs, total bytes freed, and the dry-run flag. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn prune_old( + &self, + params: SessionsPruneOldRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_PRUNEOLD, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.name.*` sub-namespace. - pub fn name(&self) -> SessionRpcName<'a> { - SessionRpcName { - session: self.session, - } + /// Flushes a session's pending events to disk. + /// + /// Wire method: `sessions.save`. + /// + /// # Parameters + /// + /// * `params` - Session ID whose pending events should be flushed to disk. + /// + /// # Returns + /// + /// Flush a session's pending events to disk. No-op when no writer exists for the session (e.g., already closed). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn save(&self, params: SessionsSaveRequest) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_SAVE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.permissions.*` sub-namespace. - pub fn permissions(&self) -> SessionRpcPermissions<'a> { - SessionRpcPermissions { - session: self.session, - } + /// Releases the in-use lock held by this process for a session. + /// + /// Wire method: `sessions.releaseLock`. + /// + /// # Parameters + /// + /// * `params` - Session ID whose in-use lock should be released. + /// + /// # Returns + /// + /// Release the in-use lock held by this process for the given session. No-op when this process does not currently hold a lock for the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn release_lock( + &self, + params: SessionsReleaseLockRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_RELEASELOCK, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.plan.*` sub-namespace. - pub fn plan(&self) -> SessionRpcPlan<'a> { - SessionRpcPlan { - session: self.session, + /// Backfills missing summary and context fields on the supplied session metadata records. + /// + /// Wire method: `sessions.enrichMetadata`. + /// + /// # Parameters + /// + /// * `params` - Session metadata records to enrich with summary and context information. + /// + /// # Returns + /// + /// The same metadata records, with summary and context fields backfilled where available. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn enrich_metadata( + &self, + params: SessionsEnrichMetadataRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_ENRICHMETADATA, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Reloads user, plugin, and (optionally) repo hooks on the active session. + /// + /// Wire method: `sessions.reloadPluginHooks`. + /// + /// # Parameters + /// + /// * `params` - Active session ID and an optional flag for deferring repo-level hooks until folder trust. + /// + /// # Returns + /// + /// Reload all hooks (user, plugin, optionally repo) and apply them to the active session. Call after installing or removing plugins so their hooks take effect immediately. No-op when no active session matches the given sessionId. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn reload_plugin_hooks( + &self, + params: SessionsReloadPluginHooksRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SESSIONS_RELOADPLUGINHOOKS, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Loads previously-deferred repo-level hooks on the active session, returning queued startup prompts. + /// + /// Wire method: `sessions.loadDeferredRepoHooks`. + /// + /// # Parameters + /// + /// * `params` - Active session ID whose deferred repo-level hooks should be loaded. + /// + /// # Returns + /// + /// Queued repo-level startup prompts and the total hook command count after loading. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn load_deferred_repo_hooks( + &self, + params: SessionsLoadDeferredRepoHooksRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call( + rpc_methods::SESSIONS_LOADDEFERREDREPOHOOKS, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Replaces the manager-wide additional plugins registered with the session manager. + /// + /// Wire method: `sessions.setAdditionalPlugins`. + /// + /// # Parameters + /// + /// * `params` - Manager-wide additional plugins to register; replaces any previously-configured set. + /// + /// # Returns + /// + /// Replace the manager-wide additional plugins. New session creations and subsequent hook reloads see the new set; already-running sessions keep their existing hook installation until the next reload. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn set_additional_plugins( + &self, + params: SessionsSetAdditionalPluginsRequest, + ) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call( + rpc_methods::SESSIONS_SETADDITIONALPLUGINS, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `skills.*` RPCs. +#[derive(Clone, Copy)] +pub struct ClientRpcSkills<'a> { + pub(crate) client: &'a Client, +} + +impl<'a> ClientRpcSkills<'a> { + /// `skills.config.*` sub-namespace. + pub fn config(&self) -> ClientRpcSkillsConfig<'a> { + ClientRpcSkillsConfig { + client: self.client, } } - /// `session.plugins.*` sub-namespace. - pub fn plugins(&self) -> SessionRpcPlugins<'a> { - SessionRpcPlugins { - session: self.session, - } - } + /// Discovers skills across global and project sources. + /// + /// Wire method: `skills.discover`. + /// + /// # Parameters + /// + /// * `params` - Optional project paths and additional skill directories to include in discovery. + /// + /// # Returns + /// + /// Skills discovered across global and project sources. + pub async fn discover(&self, params: SkillsDiscoverRequest) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::SKILLS_DISCOVER, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `skills.config.*` RPCs. +#[derive(Clone, Copy)] +pub struct ClientRpcSkillsConfig<'a> { + pub(crate) client: &'a Client, +} + +impl<'a> ClientRpcSkillsConfig<'a> { + /// Replaces the global list of disabled skills. + /// + /// Wire method: `skills.config.setDisabledSkills`. + /// + /// # Parameters + /// + /// * `params` - Skill names to mark as disabled in global configuration, replacing any previous list. + pub async fn set_disabled_skills( + &self, + params: SkillsConfigSetDisabledSkillsRequest, + ) -> Result<(), Error> { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call( + rpc_methods::SKILLS_CONFIG_SETDISABLEDSKILLS, + Some(wire_params), + ) + .await?; + Ok(()) + } +} + +/// `tools.*` RPCs. +#[derive(Clone, Copy)] +pub struct ClientRpcTools<'a> { + pub(crate) client: &'a Client, +} + +impl<'a> ClientRpcTools<'a> { + /// Lists built-in tools available for a model. + /// + /// Wire method: `tools.list`. + /// + /// # Parameters + /// + /// * `params` - Optional model identifier whose tool overrides should be applied to the listing. + /// + /// # Returns + /// + /// Built-in tools available for the requested model, with their parameters and instructions. + pub async fn list(&self, params: ToolsListRequest) -> Result { + let wire_params = serde_json::to_value(params)?; + let _value = self + .client + .call(rpc_methods::TOOLS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// Typed view over a [`Session`]'s RPC namespace. +#[derive(Clone, Copy)] +pub struct SessionRpc<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpc<'a> { + /// `session.agent.*` sub-namespace. + pub fn agent(&self) -> SessionRpcAgent<'a> { + SessionRpcAgent { + session: self.session, + } + } + + /// `session.auth.*` sub-namespace. + pub fn auth(&self) -> SessionRpcAuth<'a> { + SessionRpcAuth { + session: self.session, + } + } + + /// `session.commands.*` sub-namespace. + pub fn commands(&self) -> SessionRpcCommands<'a> { + SessionRpcCommands { + session: self.session, + } + } + + /// `session.eventLog.*` sub-namespace. + pub fn event_log(&self) -> SessionRpcEventLog<'a> { + SessionRpcEventLog { + session: self.session, + } + } + + /// `session.extensions.*` sub-namespace. + pub fn extensions(&self) -> SessionRpcExtensions<'a> { + SessionRpcExtensions { + session: self.session, + } + } + + /// `session.fleet.*` sub-namespace. + pub fn fleet(&self) -> SessionRpcFleet<'a> { + SessionRpcFleet { + session: self.session, + } + } + + /// `session.history.*` sub-namespace. + pub fn history(&self) -> SessionRpcHistory<'a> { + SessionRpcHistory { + session: self.session, + } + } + + /// `session.instructions.*` sub-namespace. + pub fn instructions(&self) -> SessionRpcInstructions<'a> { + SessionRpcInstructions { + session: self.session, + } + } + + /// `session.lsp.*` sub-namespace. + pub fn lsp(&self) -> SessionRpcLsp<'a> { + SessionRpcLsp { + session: self.session, + } + } + + /// `session.mcp.*` sub-namespace. + pub fn mcp(&self) -> SessionRpcMcp<'a> { + SessionRpcMcp { + session: self.session, + } + } + + /// `session.metadata.*` sub-namespace. + pub fn metadata(&self) -> SessionRpcMetadata<'a> { + SessionRpcMetadata { + session: self.session, + } + } + + /// `session.mode.*` sub-namespace. + pub fn mode(&self) -> SessionRpcMode<'a> { + SessionRpcMode { + session: self.session, + } + } + + /// `session.model.*` sub-namespace. + pub fn model(&self) -> SessionRpcModel<'a> { + SessionRpcModel { + session: self.session, + } + } + + /// `session.name.*` sub-namespace. + pub fn name(&self) -> SessionRpcName<'a> { + SessionRpcName { + session: self.session, + } + } + + /// `session.options.*` sub-namespace. + pub fn options(&self) -> SessionRpcOptions<'a> { + SessionRpcOptions { + session: self.session, + } + } + + /// `session.permissions.*` sub-namespace. + pub fn permissions(&self) -> SessionRpcPermissions<'a> { + SessionRpcPermissions { + session: self.session, + } + } + + /// `session.plan.*` sub-namespace. + pub fn plan(&self) -> SessionRpcPlan<'a> { + SessionRpcPlan { + session: self.session, + } + } + + /// `session.plugins.*` sub-namespace. + pub fn plugins(&self) -> SessionRpcPlugins<'a> { + SessionRpcPlugins { + session: self.session, + } + } + + /// `session.queue.*` sub-namespace. + pub fn queue(&self) -> SessionRpcQueue<'a> { + SessionRpcQueue { + session: self.session, + } + } + + /// `session.remote.*` sub-namespace. + pub fn remote(&self) -> SessionRpcRemote<'a> { + SessionRpcRemote { + session: self.session, + } + } + + /// `session.schedule.*` sub-namespace. + pub fn schedule(&self) -> SessionRpcSchedule<'a> { + SessionRpcSchedule { + session: self.session, + } + } + + /// `session.shell.*` sub-namespace. + pub fn shell(&self) -> SessionRpcShell<'a> { + SessionRpcShell { + session: self.session, + } + } + + /// `session.skills.*` sub-namespace. + pub fn skills(&self) -> SessionRpcSkills<'a> { + SessionRpcSkills { + session: self.session, + } + } + + /// `session.tasks.*` sub-namespace. + pub fn tasks(&self) -> SessionRpcTasks<'a> { + SessionRpcTasks { + session: self.session, + } + } + + /// `session.telemetry.*` sub-namespace. + pub fn telemetry(&self) -> SessionRpcTelemetry<'a> { + SessionRpcTelemetry { + session: self.session, + } + } + + /// `session.tools.*` sub-namespace. + pub fn tools(&self) -> SessionRpcTools<'a> { + SessionRpcTools { + session: self.session, + } + } + + /// `session.ui.*` sub-namespace. + pub fn ui(&self) -> SessionRpcUi<'a> { + SessionRpcUi { + session: self.session, + } + } + + /// `session.usage.*` sub-namespace. + pub fn usage(&self) -> SessionRpcUsage<'a> { + SessionRpcUsage { + session: self.session, + } + } + + /// `session.workspaces.*` sub-namespace. + pub fn workspaces(&self) -> SessionRpcWorkspaces<'a> { + SessionRpcWorkspaces { + session: self.session, + } + } + + /// Suspends the session while preserving persisted state for later resume. + /// + /// Wire method: `session.suspend`. + pub async fn suspend(&self) -> Result<(), Error> { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_SUSPEND, Some(wire_params)) + .await?; + Ok(()) + } + + /// Sends a user message to the session and returns its message ID. + /// + /// Wire method: `session.send`. + /// + /// # Parameters + /// + /// * `params` - Parameters for sending a user message to the session + /// + /// # Returns + /// + /// Result of sending a user message + pub async fn send(&self, params: SendRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_SEND, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Aborts the current agent turn. + /// + /// Wire method: `session.abort`. + /// + /// # Parameters + /// + /// * `params` - Parameters for aborting the current turn + /// + /// # Returns + /// + /// Result of aborting the current turn + pub async fn abort(&self, params: AbortRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_ABORT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Shuts down the session and persists its final state. Awaits any deferred sessionEnd hooks before resolving so user-supplied hook scripts complete before the runtime tears down. + /// + /// Wire method: `session.shutdown`. + /// + /// # Parameters + /// + /// * `params` - Parameters for shutting down the session + pub async fn shutdown(&self, params: ShutdownRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_SHUTDOWN, Some(wire_params)) + .await?; + Ok(()) + } + + /// Emits a user-visible session log event. + /// + /// Wire method: `session.log`. + /// + /// # Parameters + /// + /// * `params` - Message text, optional severity level, persistence flag, optional follow-up URL, and optional tip. + /// + /// # Returns + /// + /// Identifier of the session event that was emitted for the log message. + pub async fn log(&self, params: LogRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_LOG, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.agent.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcAgent<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcAgent<'a> { + /// Lists custom agents available to the session. + /// + /// Wire method: `session.agent.list`. + /// + /// # Returns + /// + /// Custom agents available to the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AGENT_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Gets the currently selected custom agent for the session. + /// + /// Wire method: `session.agent.getCurrent`. + /// + /// # Returns + /// + /// The currently selected custom agent, or null when using the default agent. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_current(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AGENT_GETCURRENT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Selects a custom agent for subsequent turns in the session. + /// + /// Wire method: `session.agent.select`. + /// + /// # Parameters + /// + /// * `params` - Name of the custom agent to select for subsequent turns. + /// + /// # Returns + /// + /// The newly selected custom agent. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn select(&self, params: AgentSelectRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AGENT_SELECT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Clears the selected custom agent and returns the session to the default agent. + /// + /// Wire method: `session.agent.deselect`. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn deselect(&self) -> Result<(), Error> { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AGENT_DESELECT, Some(wire_params)) + .await?; + Ok(()) + } + + /// Reloads custom agent definitions and returns the refreshed list. + /// + /// Wire method: `session.agent.reload`. + /// + /// # Returns + /// + /// Custom agents available to the session after reloading definitions from disk. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn reload(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AGENT_RELOAD, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.auth.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcAuth<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcAuth<'a> { + /// Gets authentication status and account metadata for the session. + /// + /// Wire method: `session.auth.getStatus`. + /// + /// # Returns + /// + /// Authentication status and account metadata for the session. + pub async fn get_status(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AUTH_GETSTATUS, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Updates the session's auth credentials used for outbound model and API requests. + /// + /// Wire method: `session.auth.setCredentials`. + /// + /// # Parameters + /// + /// * `params` - New auth credentials to install on the session. Omit to leave credentials unchanged. + /// + /// # Returns + /// + /// Indicates whether the credential update succeeded. + pub async fn set_credentials( + &self, + params: SessionSetCredentialsParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_AUTH_SETCREDENTIALS, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.commands.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcCommands<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcCommands<'a> { + /// Lists slash commands available in the session. + /// + /// Wire method: `session.commands.list`. + /// + /// # Returns + /// + /// Slash commands available in the session, after applying any include/exclude filters. + pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_COMMANDS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Lists slash commands available in the session. + /// + /// Wire method: `session.commands.list`. + /// + /// # Parameters + /// + /// * `params` - Optional filters controlling which command sources to include in the listing. + /// + /// # Returns + /// + /// Slash commands available in the session, after applying any include/exclude filters. + pub async fn list_with_params( + &self, + params: CommandsListRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_COMMANDS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Invokes a slash command in the session. + /// + /// Wire method: `session.commands.invoke`. + /// + /// # Parameters + /// + /// * `params` - Slash command name and optional raw input string to invoke. + /// + /// # Returns + /// + /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). + pub async fn invoke( + &self, + params: CommandsInvokeRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_COMMANDS_INVOKE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Reports completion of a pending client-handled slash command. + /// + /// Wire method: `session.commands.handlePendingCommand`. + /// + /// # Parameters + /// + /// * `params` - Pending command request ID and an optional error if the client handler failed. + /// + /// # Returns + /// + /// Indicates whether the pending client-handled command was completed successfully. + pub async fn handle_pending_command( + &self, + params: CommandsHandlePendingCommandRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_COMMANDS_HANDLEPENDINGCOMMAND, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Executes a slash command synchronously and returns any error. + /// + /// Wire method: `session.commands.execute`. + /// + /// # Parameters + /// + /// * `params` - Slash command name and argument string to execute synchronously. + /// + /// # Returns + /// + /// Error message produced while executing the command, if any. + pub async fn execute( + &self, + params: ExecuteCommandParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_COMMANDS_EXECUTE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Enqueues a slash command for FIFO processing on the local session. + /// + /// Wire method: `session.commands.enqueue`. + /// + /// # Parameters + /// + /// * `params` - Slash-prefixed command string to enqueue for FIFO processing. + /// + /// # Returns + /// + /// Indicates whether the command was accepted into the local execution queue. + pub async fn enqueue( + &self, + params: EnqueueCommandParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_COMMANDS_ENQUEUE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Reports whether the host actually executed a queued command and whether to continue processing. + /// + /// Wire method: `session.commands.respondToQueuedCommand`. + /// + /// # Parameters + /// + /// * `params` - Queued-command request ID and the result indicating whether the host executed it (and whether to stop processing further queued commands). + /// + /// # Returns + /// + /// Indicates whether the queued-command response was matched to a pending request. + pub async fn respond_to_queued_command( + &self, + params: CommandsRespondToQueuedCommandRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_COMMANDS_RESPONDTOQUEUEDCOMMAND, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.eventLog.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcEventLog<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcEventLog<'a> { + /// Reads a batch of session events from a cursor, optionally waiting for new events. + /// + /// Wire method: `session.eventLog.read`. + /// + /// # Parameters + /// + /// * `params` - Cursor, batch size, and optional long-poll/filter parameters for reading session events. + /// + /// # Returns + /// + /// Batch of session events returned by a read, with cursor and continuation metadata. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn read(&self, params: EventLogReadRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EVENTLOG_READ, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Returns a snapshot of the current tail cursor without consuming events. + /// + /// Wire method: `session.eventLog.tail`. + /// + /// # Returns + /// + /// Snapshot of the current tail cursor without returning any events. Use this when a consumer wants to subscribe to live events going forward without first paginating through the entire persisted history (which would happen if `read` were called without a cursor on a long-lived session). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn tail(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EVENTLOG_TAIL, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Registers consumer interest in an event type for runtime gating purposes. + /// + /// Wire method: `session.eventLog.registerInterest`. + /// + /// # Parameters + /// + /// * `params` - Event type to register consumer interest for, used by runtime gating logic. + /// + /// # Returns + /// + /// Opaque handle representing an event-type interest registration. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn register_interest( + &self, + params: RegisterEventInterestParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_EVENTLOG_REGISTERINTEREST, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Releases a consumer's previously-registered interest in an event type. + /// + /// Wire method: `session.eventLog.releaseInterest`. + /// + /// # Parameters + /// + /// * `params` - Opaque handle previously returned by `registerInterest` to release. + /// + /// # Returns + /// + /// Indicates whether the operation succeeded. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn release_interest( + &self, + params: ReleaseEventInterestParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_EVENTLOG_RELEASEINTEREST, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.extensions.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcExtensions<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcExtensions<'a> { + /// Lists extensions discovered for the session and their current status. + /// + /// Wire method: `session.extensions.list`. + /// + /// # Returns + /// + /// Extensions discovered for the session, with their current status. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EXTENSIONS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Enables an extension for the session. + /// + /// Wire method: `session.extensions.enable`. + /// + /// # Parameters + /// + /// * `params` - Source-qualified extension identifier to enable for the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn enable(&self, params: ExtensionsEnableRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EXTENSIONS_ENABLE, Some(wire_params)) + .await?; + Ok(()) + } + + /// Disables an extension for the session. + /// + /// Wire method: `session.extensions.disable`. + /// + /// # Parameters + /// + /// * `params` - Source-qualified extension identifier to disable for the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn disable(&self, params: ExtensionsDisableRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EXTENSIONS_DISABLE, Some(wire_params)) + .await?; + Ok(()) + } + + /// Reloads extension definitions and processes for the session. + /// + /// Wire method: `session.extensions.reload`. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn reload(&self) -> Result<(), Error> { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_EXTENSIONS_RELOAD, Some(wire_params)) + .await?; + Ok(()) + } +} + +/// `session.fleet.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcFleet<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcFleet<'a> { + /// Starts fleet mode by submitting the fleet orchestration prompt to the session. + /// + /// Wire method: `session.fleet.start`. + /// + /// # Parameters + /// + /// * `params` - Optional user prompt to combine with the fleet orchestration instructions. + /// + /// # Returns + /// + /// Indicates whether fleet mode was successfully activated. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn start(&self, params: FleetStartRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_FLEET_START, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.history.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcHistory<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcHistory<'a> { + /// Compacts the session history to reduce context usage. + /// + /// Wire method: `session.history.compact`. + /// + /// # Returns + /// + /// Compaction outcome with the number of tokens and messages removed, summary text, and the resulting context window breakdown. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn compact(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_HISTORY_COMPACT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Truncates persisted session history to a specific event. + /// + /// Wire method: `session.history.truncate`. + /// + /// # Parameters + /// + /// * `params` - Identifier of the event to truncate to; this event and all later events are removed. + /// + /// # Returns + /// + /// Number of events that were removed by the truncation. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn truncate( + &self, + params: HistoryTruncateRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_HISTORY_TRUNCATE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Cancels any in-progress background compaction on a local session. + /// + /// Wire method: `session.history.cancelBackgroundCompaction`. + /// + /// # Returns + /// + /// Indicates whether an in-progress background compaction was cancelled. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn cancel_background_compaction( + &self, + ) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_HISTORY_CANCELBACKGROUNDCOMPACTION, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Aborts any in-progress manual compaction on a local session. + /// + /// Wire method: `session.history.abortManualCompaction`. + /// + /// # Returns + /// + /// Indicates whether an in-progress manual compaction was aborted. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn abort_manual_compaction( + &self, + ) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_HISTORY_ABORTMANUALCOMPACTION, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Produces a markdown summary of the session's conversation context for hand-off scenarios. + /// + /// Wire method: `session.history.summarizeForHandoff`. + /// + /// # Returns + /// + /// Markdown summary of the conversation context (empty when not available). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn summarize_for_handoff(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_HISTORY_SUMMARIZEFORHANDOFF, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.instructions.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcInstructions<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcInstructions<'a> { + /// Gets instruction sources loaded for the session. + /// + /// Wire method: `session.instructions.getSources`. + /// + /// # Returns + /// + /// Instruction sources loaded for the session, in merge order. + pub async fn get_sources(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_INSTRUCTIONS_GETSOURCES, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.lsp.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcLsp<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcLsp<'a> { + /// Loads the merged LSP configuration set for the session's working directory. + /// + /// Wire method: `session.lsp.initialize`. + /// + /// # Parameters + /// + /// * `params` - Parameters for (re)loading the merged LSP configuration set. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn initialize(&self, params: LspInitializeRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_LSP_INITIALIZE, Some(wire_params)) + .await?; + Ok(()) + } +} + +/// `session.mcp.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcMcp<'a> { + pub(crate) session: &'a Session, +} - /// `session.remote.*` sub-namespace. - pub fn remote(&self) -> SessionRpcRemote<'a> { - SessionRpcRemote { +impl<'a> SessionRpcMcp<'a> { + /// `session.mcp.oauth.*` sub-namespace. + pub fn oauth(&self) -> SessionRpcMcpOauth<'a> { + SessionRpcMcpOauth { session: self.session, } } - /// `session.shell.*` sub-namespace. - pub fn shell(&self) -> SessionRpcShell<'a> { - SessionRpcShell { - session: self.session, - } + /// Lists MCP servers configured for the session and their connection status. + /// + /// Wire method: `session.mcp.list`. + /// + /// # Returns + /// + /// MCP servers configured for the session, with their connection status. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.skills.*` sub-namespace. - pub fn skills(&self) -> SessionRpcSkills<'a> { - SessionRpcSkills { - session: self.session, - } + /// Enables an MCP server for the session. + /// + /// Wire method: `session.mcp.enable`. + /// + /// # Parameters + /// + /// * `params` - Name of the MCP server to enable for the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn enable(&self, params: McpEnableRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_ENABLE, Some(wire_params)) + .await?; + Ok(()) } - /// `session.tasks.*` sub-namespace. - pub fn tasks(&self) -> SessionRpcTasks<'a> { - SessionRpcTasks { - session: self.session, - } + /// Disables an MCP server for the session. + /// + /// Wire method: `session.mcp.disable`. + /// + /// # Parameters + /// + /// * `params` - Name of the MCP server to disable for the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn disable(&self, params: McpDisableRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_DISABLE, Some(wire_params)) + .await?; + Ok(()) } - /// `session.tools.*` sub-namespace. - pub fn tools(&self) -> SessionRpcTools<'a> { - SessionRpcTools { - session: self.session, - } + /// Reloads MCP server connections for the session. + /// + /// Wire method: `session.mcp.reload`. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn reload(&self) -> Result<(), Error> { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_RELOAD, Some(wire_params)) + .await?; + Ok(()) } - /// `session.ui.*` sub-namespace. - pub fn ui(&self) -> SessionRpcUi<'a> { - SessionRpcUi { - session: self.session, - } + /// Runs an MCP sampling inference on behalf of an MCP server. + /// + /// Wire method: `session.mcp.executeSampling`. + /// + /// # Parameters + /// + /// * `params` - Identifiers and raw MCP CreateMessageRequest params used to run a sampling inference. + /// + /// # Returns + /// + /// Outcome of an MCP sampling execution: success result, failure error, or cancellation. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn execute_sampling( + &self, + params: McpExecuteSamplingParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_EXECUTESAMPLING, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.usage.*` sub-namespace. - pub fn usage(&self) -> SessionRpcUsage<'a> { - SessionRpcUsage { - session: self.session, - } + /// Cancels an in-flight MCP sampling execution by request ID. + /// + /// Wire method: `session.mcp.cancelSamplingExecution`. + /// + /// # Parameters + /// + /// * `params` - The requestId previously passed to executeSampling that should be cancelled. + /// + /// # Returns + /// + /// Indicates whether an in-flight sampling execution with the given requestId was found and cancelled. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn cancel_sampling_execution( + &self, + params: McpCancelSamplingExecutionParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_MCP_CANCELSAMPLINGEXECUTION, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) } - /// `session.workspaces.*` sub-namespace. - pub fn workspaces(&self) -> SessionRpcWorkspaces<'a> { - SessionRpcWorkspaces { - session: self.session, - } + /// Sets how environment-variable values supplied to MCP servers are resolved (direct or indirect). + /// + /// Wire method: `session.mcp.setEnvValueMode`. + /// + /// # Parameters + /// + /// * `params` - Mode controlling how MCP server env values are resolved (`direct` or `indirect`). + /// + /// # Returns + /// + /// Env-value mode recorded on the session after the update. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn set_env_value_mode( + &self, + params: McpSetEnvValueModeParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MCP_SETENVVALUEMODE, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) } - /// Suspends the session while preserving persisted state for later resume. + /// Removes the auto-managed `github` MCP server when present. /// - /// Wire method: `session.suspend`. - pub async fn suspend(&self) -> Result<(), Error> { + /// Wire method: `session.mcp.removeGitHub`. + /// + /// # Returns + /// + /// Indicates whether the auto-managed `github` MCP server was removed (false when nothing to remove). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn remove_git_hub(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_SUSPEND, Some(wire_params)) + .call(rpc_methods::SESSION_MCP_REMOVEGITHUB, Some(wire_params)) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } +} + +/// `session.mcp.oauth.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcMcpOauth<'a> { + pub(crate) session: &'a Session, +} - /// Emits a user-visible session log event. +impl<'a> SessionRpcMcpOauth<'a> { + /// Starts OAuth authentication for a remote MCP server. /// - /// Wire method: `session.log`. + /// Wire method: `session.mcp.oauth.login`. /// /// # Parameters /// - /// * `params` - Message text, optional severity level, persistence flag, and optional follow-up URL. + /// * `params` - Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. /// /// # Returns /// - /// Identifier of the session event that was emitted for the log message. - pub async fn log(&self, params: LogRequest) -> Result { + /// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn login(&self, params: McpOauthLoginRequest) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_LOG, Some(wire_params)) + .call(rpc_methods::SESSION_MCP_OAUTH_LOGIN, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } } -/// `session.agent.*` RPCs. +/// `session.metadata.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcAgent<'a> { +pub struct SessionRpcMetadata<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcAgent<'a> { - /// Lists custom agents available to the session. +impl<'a> SessionRpcMetadata<'a> { + /// Returns a snapshot of the session's identifying metadata, mode, agent, and remote info. /// - /// Wire method: `session.agent.list`. + /// Wire method: `session.metadata.snapshot`. /// /// # Returns /// - /// Custom agents available to the session. + /// Point-in-time snapshot of slow-changing session identifier and state fields /// ///
/// @@ -750,23 +2546,23 @@ impl<'a> SessionRpcAgent<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn list(&self) -> Result { + pub async fn snapshot(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_AGENT_LIST, Some(wire_params)) + .call(rpc_methods::SESSION_METADATA_SNAPSHOT, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Gets the currently selected custom agent for the session. + /// Reports whether the local session is currently processing user/agent messages. /// - /// Wire method: `session.agent.getCurrent`. + /// Wire method: `session.metadata.isProcessing`. /// /// # Returns /// - /// The currently selected custom agent, or null when using the default agent. + /// Indicates whether the local session is currently processing a turn or background continuation. /// ///
/// @@ -775,27 +2571,30 @@ impl<'a> SessionRpcAgent<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn get_current(&self) -> Result { + pub async fn is_processing(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_AGENT_GETCURRENT, Some(wire_params)) + .call( + rpc_methods::SESSION_METADATA_ISPROCESSING, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } - /// Selects a custom agent for subsequent turns in the session. + /// Returns the token breakdown for the session's current context window for a given model. /// - /// Wire method: `session.agent.select`. + /// Wire method: `session.metadata.contextInfo`. /// /// # Parameters /// - /// * `params` - Name of the custom agent to select for subsequent turns. + /// * `params` - Model identifier and token limits used to compute the context-info breakdown. /// /// # Returns /// - /// The newly selected custom agent. + /// Token breakdown for the session's current context window, or null if uninitialized. /// ///
/// @@ -804,20 +2603,31 @@ impl<'a> SessionRpcAgent<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn select(&self, params: AgentSelectRequest) -> Result { + pub async fn context_info( + &self, + params: MetadataContextInfoRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_AGENT_SELECT, Some(wire_params)) + .call(rpc_methods::SESSION_METADATA_CONTEXTINFO, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Clears the selected custom agent and returns the session to the default agent. + /// Records a working-directory/git context change and emits a `session.context_changed` event. /// - /// Wire method: `session.agent.deselect`. + /// Wire method: `session.metadata.recordContextChange`. + /// + /// # Parameters + /// + /// * `params` - Updated working-directory/git context to record on the session. + /// + /// # Returns + /// + /// Notify the session that its working directory context has changed. Emits a `session.context_changed` event so consumers (telemetry, OTel tracker, ACP, the timeline UI) can react. Use this when the host has detected a cwd/branch/repo change outside the session's normal lifecycle (e.g., after a shell command in interactive mode). /// ///
/// @@ -826,23 +2636,34 @@ impl<'a> SessionRpcAgent<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn deselect(&self) -> Result<(), Error> { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + pub async fn record_context_change( + &self, + params: MetadataRecordContextChangeRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_AGENT_DESELECT, Some(wire_params)) + .call( + rpc_methods::SESSION_METADATA_RECORDCONTEXTCHANGE, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } - /// Reloads custom agent definitions and returns the refreshed list. + /// Updates the session's recorded working directory. /// - /// Wire method: `session.agent.reload`. + /// Wire method: `session.metadata.setWorkingDirectory`. + /// + /// # Parameters + /// + /// * `params` - Absolute path to set as the session's new working directory. /// /// # Returns /// - /// Custom agents available to the session after reloading definitions from disk. + /// Update the session's working directory. Used by the host when the user explicitly changes cwd (e.g., the `/cd` slash command). The host is responsible for `process.chdir` and any related side-effects (file index, etc.); this method only updates the session's own recorded path. /// ///
/// @@ -851,854 +2672,935 @@ impl<'a> SessionRpcAgent<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn reload(&self) -> Result { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + pub async fn set_working_directory( + &self, + params: MetadataSetWorkingDirectoryRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_AGENT_RELOAD, Some(wire_params)) + .call( + rpc_methods::SESSION_METADATA_SETWORKINGDIRECTORY, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Re-tokenizes the session's existing messages against a model and returns aggregate token totals. + /// + /// Wire method: `session.metadata.recomputeContextTokens`. + /// + /// # Parameters + /// + /// * `params` - Model identifier to use when re-tokenizing the session's existing messages. + /// + /// # Returns + /// + /// Re-tokenize the session's existing messages against `modelId` and return the token totals. Useful for hosts that want an initial estimate of context usage on session resume, before the next agent turn fires `session.context_info_changed` events. Returns zeros for an empty session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn recompute_context_tokens( + &self, + params: MetadataRecomputeContextTokensRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_METADATA_RECOMPUTECONTEXTTOKENS, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } } -/// `session.auth.*` RPCs. +/// `session.mode.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcAuth<'a> { +pub struct SessionRpcMode<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcAuth<'a> { - /// Gets authentication status and account metadata for the session. +impl<'a> SessionRpcMode<'a> { + /// Gets the current agent interaction mode. /// - /// Wire method: `session.auth.getStatus`. + /// Wire method: `session.mode.get`. /// /// # Returns /// - /// Authentication status and account metadata for the session. - pub async fn get_status(&self) -> Result { + /// The session mode the agent is operating in + pub async fn get(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_AUTH_GETSTATUS, Some(wire_params)) + .call(rpc_methods::SESSION_MODE_GET, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } + + /// Sets the current agent interaction mode. + /// + /// Wire method: `session.mode.set`. + /// + /// # Parameters + /// + /// * `params` - Agent interaction mode to apply to the session. + pub async fn set(&self, params: ModeSetRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_MODE_SET, Some(wire_params)) + .await?; + Ok(()) + } } -/// `session.commands.*` RPCs. +/// `session.model.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcCommands<'a> { +pub struct SessionRpcModel<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcCommands<'a> { - /// Lists slash commands available in the session. +impl<'a> SessionRpcModel<'a> { + /// Gets the currently selected model for the session. /// - /// Wire method: `session.commands.list`. + /// Wire method: `session.model.getCurrent`. /// /// # Returns /// - /// Slash commands available in the session, after applying any include/exclude filters. - pub async fn list(&self) -> Result { + /// The currently selected model and reasoning effort for the session. + pub async fn get_current(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_COMMANDS_LIST, Some(wire_params)) + .call(rpc_methods::SESSION_MODEL_GETCURRENT, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Lists slash commands available in the session. + /// Switches the session to a model and optional reasoning configuration. /// - /// Wire method: `session.commands.list`. + /// Wire method: `session.model.switchTo`. /// /// # Parameters /// - /// * `params` - Optional filters controlling which command sources to include in the listing. + /// * `params` - Target model identifier and optional reasoning effort, summary, and capability overrides. /// /// # Returns /// - /// Slash commands available in the session, after applying any include/exclude filters. - pub async fn list_with_params( + /// The model identifier active on the session after the switch. + pub async fn switch_to( &self, - params: CommandsListRequest, - ) -> Result { + params: ModelSwitchToRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_COMMANDS_LIST, Some(wire_params)) + .call(rpc_methods::SESSION_MODEL_SWITCHTO, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Invokes a slash command in the session. + /// Updates the session's reasoning effort without changing the selected model. + /// + /// Wire method: `session.model.setReasoningEffort`. + /// + /// # Parameters + /// + /// * `params` - Reasoning effort level to apply to the currently selected model. + /// + /// # Returns + /// + /// Update the session's reasoning effort without changing the selected model. Use `switchTo` instead when you also need to change the model. The runtime stores the effort on the session and applies it to subsequent turns. + pub async fn set_reasoning_effort( + &self, + params: ModelSetReasoningEffortRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_MODEL_SETREASONINGEFFORT, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.name.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcName<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcName<'a> { + /// Gets the session's friendly name. + /// + /// Wire method: `session.name.get`. + /// + /// # Returns + /// + /// The session's friendly name, or null when not yet set. + pub async fn get(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_NAME_GET, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Sets the session's friendly name. + /// + /// Wire method: `session.name.set`. + /// + /// # Parameters + /// + /// * `params` - New friendly name to apply to the session. + pub async fn set(&self, params: NameSetRequest) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_NAME_SET, Some(wire_params)) + .await?; + Ok(()) + } + + /// Persists an auto-generated session summary as the session's name when no user-set name exists. + /// + /// Wire method: `session.name.setAuto`. + /// + /// # Parameters + /// + /// * `params` - Auto-generated session summary to apply as the session's name when no user-set name exists. + /// + /// # Returns + /// + /// Indicates whether the auto-generated summary was applied as the session's name. + pub async fn set_auto(&self, params: NameSetAutoRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_NAME_SETAUTO, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } +} + +/// `session.options.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcOptions<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcOptions<'a> { + /// Patches the genuinely-mutable subset of session options. /// - /// Wire method: `session.commands.invoke`. + /// Wire method: `session.options.update`. /// /// # Parameters /// - /// * `params` - Slash command name and optional raw input string to invoke. + /// * `params` - Patch of mutable session options to apply to the running session. /// /// # Returns /// - /// Result of invoking the slash command (text output, prompt to send to the agent, or completion). - pub async fn invoke( + /// Indicates whether the session options patch was applied successfully. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn update( &self, - params: CommandsInvokeRequest, - ) -> Result { + params: SessionUpdateOptionsParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_COMMANDS_INVOKE, Some(wire_params)) + .call(rpc_methods::SESSION_OPTIONS_UPDATE, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } +} + +/// `session.permissions.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcPermissions<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcPermissions<'a> { + /// `session.permissions.paths.*` sub-namespace. + pub fn paths(&self) -> SessionRpcPermissionsPaths<'a> { + SessionRpcPermissionsPaths { + session: self.session, + } + } - /// Reports completion of a pending client-handled slash command. + /// `session.permissions.urls.*` sub-namespace. + pub fn urls(&self) -> SessionRpcPermissionsUrls<'a> { + SessionRpcPermissionsUrls { + session: self.session, + } + } + + /// Replaces selected permission policy fields (rules, paths, URLs, exclusions, allow-all flags) on the session. /// - /// Wire method: `session.commands.handlePendingCommand`. + /// Wire method: `session.permissions.configure`. /// /// # Parameters /// - /// * `params` - Pending command request ID and an optional error if the client handler failed. + /// * `params` - Patch of permission policy fields to apply (omit a field to leave it unchanged). /// /// # Returns /// - /// Indicates whether the pending client-handled command was completed successfully. - pub async fn handle_pending_command( + /// Indicates whether the operation succeeded. + pub async fn configure( &self, - params: CommandsHandlePendingCommandRequest, - ) -> Result { + params: PermissionsConfigureParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() .call( - rpc_methods::SESSION_COMMANDS_HANDLEPENDINGCOMMAND, + rpc_methods::SESSION_PERMISSIONS_CONFIGURE, Some(wire_params), ) .await?; Ok(serde_json::from_value(_value)?) } - /// Responds to a queued command request from the session. + /// Provides a decision for a pending tool permission request. /// - /// Wire method: `session.commands.respondToQueuedCommand`. + /// Wire method: `session.permissions.handlePendingPermissionRequest`. /// /// # Parameters /// - /// * `params` - Queued command request ID and the result indicating whether the client handled it. + /// * `params` - Pending permission request ID and the decision to apply (approve/reject and scope). /// /// # Returns /// - /// Indicates whether the queued-command response was accepted by the session. - pub async fn respond_to_queued_command( + /// Indicates whether the permission decision was applied; false when the request was already resolved. + pub async fn handle_pending_permission_request( &self, - params: CommandsRespondToQueuedCommandRequest, - ) -> Result { + params: PermissionDecisionRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() .call( - rpc_methods::SESSION_COMMANDS_RESPONDTOQUEUEDCOMMAND, + rpc_methods::SESSION_PERMISSIONS_HANDLEPENDINGPERMISSIONREQUEST, Some(wire_params), ) .await?; Ok(serde_json::from_value(_value)?) } -} - -/// `session.extensions.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcExtensions<'a> { - pub(crate) session: &'a Session, -} -impl<'a> SessionRpcExtensions<'a> { - /// Lists extensions discovered for the session and their current status. + /// Reconstructs the set of pending tool permission requests from the session's event history. /// - /// Wire method: `session.extensions.list`. + /// Wire method: `session.permissions.pendingRequests`. /// /// # Returns /// - /// Extensions discovered for the session, with their current status. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn list(&self) -> Result { + /// List of pending permission requests reconstructed from event history. + pub async fn pending_requests(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_EXTENSIONS_LIST, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_PENDINGREQUESTS, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } - /// Enables an extension for the session. + /// Enables or disables automatic approval of tool permission requests for the session. /// - /// Wire method: `session.extensions.enable`. + /// Wire method: `session.permissions.setApproveAll`. /// /// # Parameters /// - /// * `params` - Source-qualified extension identifier to enable for the session. - /// - ///
+ /// * `params` - Allow-all toggle for tool permission requests, with an optional telemetry source. /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// # Returns /// - ///
- pub async fn enable(&self, params: ExtensionsEnableRequest) -> Result<(), Error> { + /// Indicates whether the operation succeeded. + pub async fn set_approve_all( + &self, + params: PermissionsSetApproveAllRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_EXTENSIONS_ENABLE, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_SETAPPROVEALL, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } - /// Disables an extension for the session. + /// Adds or removes session-scoped or location-scoped permission rules. /// - /// Wire method: `session.extensions.disable`. + /// Wire method: `session.permissions.modifyRules`. /// /// # Parameters /// - /// * `params` - Source-qualified extension identifier to disable for the session. - /// - ///
+ /// * `params` - Scope and add/remove instructions for modifying session- or location-scoped permission rules. /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// # Returns /// - ///
- pub async fn disable(&self, params: ExtensionsDisableRequest) -> Result<(), Error> { + /// Indicates whether the operation succeeded. + pub async fn modify_rules( + &self, + params: PermissionsModifyRulesParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_EXTENSIONS_DISABLE, Some(wire_params)) - .await?; - Ok(()) - } - - /// Reloads extension definitions and processes for the session. - /// - /// Wire method: `session.extensions.reload`. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn reload(&self) -> Result<(), Error> { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); - let _value = self - .session - .client() - .call(rpc_methods::SESSION_EXTENSIONS_RELOAD, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_MODIFYRULES, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } -} - -/// `session.fleet.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcFleet<'a> { - pub(crate) session: &'a Session, -} -impl<'a> SessionRpcFleet<'a> { - /// Starts fleet mode by submitting the fleet orchestration prompt to the session. + /// Sets whether the client wants permission prompts bridged into session events. /// - /// Wire method: `session.fleet.start`. + /// Wire method: `session.permissions.setRequired`. /// /// # Parameters /// - /// * `params` - Optional user prompt to combine with the fleet orchestration instructions. + /// * `params` - Toggles whether permission prompts should be bridged into session events for this client. /// /// # Returns /// - /// Indicates whether fleet mode was successfully activated. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn start(&self, params: FleetStartRequest) -> Result { + /// Indicates whether the operation succeeded. + pub async fn set_required( + &self, + params: PermissionsSetRequiredRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_FLEET_START, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_SETREQUIRED, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } -} - -/// `session.history.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcHistory<'a> { - pub(crate) session: &'a Session, -} -impl<'a> SessionRpcHistory<'a> { - /// Compacts the session history to reduce context usage. + /// Clears session-scoped tool permission approvals. /// - /// Wire method: `session.history.compact`. + /// Wire method: `session.permissions.resetSessionApprovals`. /// /// # Returns /// - /// Compaction outcome with the number of tokens and messages removed and the resulting context window breakdown. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn compact(&self) -> Result { + /// Indicates whether the operation succeeded. + pub async fn reset_session_approvals( + &self, + ) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_HISTORY_COMPACT, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_RESETSESSIONAPPROVALS, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } - /// Truncates persisted session history to a specific event. + /// Notifies the runtime that a permission prompt UI has been shown to the user. /// - /// Wire method: `session.history.truncate`. + /// Wire method: `session.permissions.notifyPromptShown`. /// /// # Parameters /// - /// * `params` - Identifier of the event to truncate to; this event and all later events are removed. + /// * `params` - Notification payload describing the permission prompt that the client just rendered. /// /// # Returns /// - /// Number of events that were removed by the truncation. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn truncate( + /// Indicates whether the operation succeeded. + pub async fn notify_prompt_shown( &self, - params: HistoryTruncateRequest, - ) -> Result { + params: PermissionPromptShownNotification, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_HISTORY_TRUNCATE, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_NOTIFYPROMPTSHOWN, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } } -/// `session.instructions.*` RPCs. +/// `session.permissions.paths.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcInstructions<'a> { +pub struct SessionRpcPermissionsPaths<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcInstructions<'a> { - /// Gets instruction sources loaded for the session. +impl<'a> SessionRpcPermissionsPaths<'a> { + /// Returns the session's allowed directories and primary working directory. /// - /// Wire method: `session.instructions.getSources`. + /// Wire method: `session.permissions.paths.list`. /// /// # Returns /// - /// Instruction sources loaded for the session, in merge order. - pub async fn get_sources(&self) -> Result { + /// Snapshot of the session's allow-listed directories and primary working directory. + pub async fn list(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() .call( - rpc_methods::SESSION_INSTRUCTIONS_GETSOURCES, + rpc_methods::SESSION_PERMISSIONS_PATHS_LIST, Some(wire_params), ) .await?; Ok(serde_json::from_value(_value)?) } -} - -/// `session.mcp.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcMcp<'a> { - pub(crate) session: &'a Session, -} - -impl<'a> SessionRpcMcp<'a> { - /// `session.mcp.oauth.*` sub-namespace. - pub fn oauth(&self) -> SessionRpcMcpOauth<'a> { - SessionRpcMcpOauth { - session: self.session, - } - } - /// Lists MCP servers configured for the session and their connection status. - /// - /// Wire method: `session.mcp.list`. - /// - /// # Returns + /// Adds a directory to the session's allow-list. /// - /// MCP servers configured for the session, with their connection status. + /// Wire method: `session.permissions.paths.add`. /// - ///
+ /// # Parameters /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// * `params` - Directory path to add to the session's allowed directories. /// - ///
- pub async fn list(&self) -> Result { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + /// # Returns + /// + /// Indicates whether the operation succeeded. + pub async fn add( + &self, + params: PermissionPathsAddParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MCP_LIST, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_PATHS_ADD, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } - /// Enables an MCP server for the session. + /// Updates the session's primary working directory used by the permission policy. /// - /// Wire method: `session.mcp.enable`. + /// Wire method: `session.permissions.paths.updatePrimary`. /// /// # Parameters /// - /// * `params` - Name of the MCP server to enable for the session. - /// - ///
+ /// * `params` - Directory path to set as the session's new primary working directory. /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// # Returns /// - ///
- pub async fn enable(&self, params: McpEnableRequest) -> Result<(), Error> { + /// Indicates whether the operation succeeded. + pub async fn update_primary( + &self, + params: PermissionPathsUpdatePrimaryParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MCP_ENABLE, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_PATHS_UPDATEPRIMARY, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } - /// Disables an MCP server for the session. + /// Reports whether a path falls within any of the session's allowed directories. /// - /// Wire method: `session.mcp.disable`. + /// Wire method: `session.permissions.paths.isPathWithinAllowedDirectories`. /// /// # Parameters /// - /// * `params` - Name of the MCP server to disable for the session. - /// - ///
+ /// * `params` - Path to evaluate against the session's allowed directories. /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// # Returns /// - ///
- pub async fn disable(&self, params: McpDisableRequest) -> Result<(), Error> { + /// Indicates whether the supplied path is within the session's allowed directories. + pub async fn is_path_within_allowed_directories( + &self, + params: PermissionPathsAllowedCheckParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MCP_DISABLE, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_PATHS_ISPATHWITHINALLOWEDDIRECTORIES, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } - /// Reloads MCP server connections for the session. + /// Reports whether a path falls within the session's workspace (primary) directory. /// - /// Wire method: `session.mcp.reload`. + /// Wire method: `session.permissions.paths.isPathWithinWorkspace`. /// - ///
+ /// # Parameters /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. + /// * `params` - Path to evaluate against the session's workspace (primary) directory. /// - ///
- pub async fn reload(&self) -> Result<(), Error> { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + /// # Returns + /// + /// Indicates whether the supplied path is within the session's workspace directory. + pub async fn is_path_within_workspace( + &self, + params: PermissionPathsWorkspaceCheckParams, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MCP_RELOAD, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_PATHS_ISPATHWITHINWORKSPACE, + Some(wire_params), + ) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } } -/// `session.mcp.oauth.*` RPCs. +/// `session.permissions.urls.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcMcpOauth<'a> { +pub struct SessionRpcPermissionsUrls<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcMcpOauth<'a> { - /// Starts OAuth authentication for a remote MCP server. +impl<'a> SessionRpcPermissionsUrls<'a> { + /// Toggles the runtime's URL-permission policy between unrestricted and restricted modes. /// - /// Wire method: `session.mcp.oauth.login`. + /// Wire method: `session.permissions.urls.setUnrestrictedMode`. /// /// # Parameters /// - /// * `params` - Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. + /// * `params` - Whether the URL-permission policy should run in unrestricted mode. /// /// # Returns /// - /// OAuth authorization URL the caller should open, or empty when cached tokens already authenticated the server. - /// - ///
- /// - /// **Experimental.** This API is part of an experimental wire-protocol surface - /// and may change or be removed in future SDK or CLI releases. Pin both the - /// SDK and CLI versions if your code depends on it. - /// - ///
- pub async fn login(&self, params: McpOauthLoginRequest) -> Result { + /// Indicates whether the operation succeeded. + pub async fn set_unrestricted_mode( + &self, + params: PermissionUrlsSetUnrestrictedModeParams, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MCP_OAUTH_LOGIN, Some(wire_params)) + .call( + rpc_methods::SESSION_PERMISSIONS_URLS_SETUNRESTRICTEDMODE, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } } -/// `session.mode.*` RPCs. +/// `session.plan.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcMode<'a> { +pub struct SessionRpcPlan<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcMode<'a> { - /// Gets the current agent interaction mode. +impl<'a> SessionRpcPlan<'a> { + /// Reads the session plan file from the workspace. /// - /// Wire method: `session.mode.get`. + /// Wire method: `session.plan.read`. /// /// # Returns /// - /// The session mode the agent is operating in - pub async fn get(&self) -> Result { + /// Existence, contents, and resolved path of the session plan file. + pub async fn read(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_MODE_GET, Some(wire_params)) + .call(rpc_methods::SESSION_PLAN_READ, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Sets the current agent interaction mode. + /// Writes new content to the session plan file. /// - /// Wire method: `session.mode.set`. + /// Wire method: `session.plan.update`. /// /// # Parameters /// - /// * `params` - Agent interaction mode to apply to the session. - pub async fn set(&self, params: ModeSetRequest) -> Result<(), Error> { + /// * `params` - Replacement contents to write to the session plan file. + pub async fn update(&self, params: PlanUpdateRequest) -> Result<(), Error> { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_MODE_SET, Some(wire_params)) + .call(rpc_methods::SESSION_PLAN_UPDATE, Some(wire_params)) .await?; Ok(()) } -} - -/// `session.model.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcModel<'a> { - pub(crate) session: &'a Session, -} -impl<'a> SessionRpcModel<'a> { - /// Gets the currently selected model for the session. - /// - /// Wire method: `session.model.getCurrent`. - /// - /// # Returns + /// Deletes the session plan file from the workspace. /// - /// The currently selected model for the session. - pub async fn get_current(&self) -> Result { + /// Wire method: `session.plan.delete`. + pub async fn delete(&self) -> Result<(), Error> { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_MODEL_GETCURRENT, Some(wire_params)) - .await?; - Ok(serde_json::from_value(_value)?) - } - - /// Switches the session to a model and optional reasoning configuration. - /// - /// Wire method: `session.model.switchTo`. - /// - /// # Parameters - /// - /// * `params` - Target model identifier and optional reasoning effort, summary, and capability overrides. - /// - /// # Returns - /// - /// The model identifier active on the session after the switch. - pub async fn switch_to( - &self, - params: ModelSwitchToRequest, - ) -> Result { - let mut wire_params = serde_json::to_value(params)?; - wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); - let _value = self - .session - .client() - .call(rpc_methods::SESSION_MODEL_SWITCHTO, Some(wire_params)) + .call(rpc_methods::SESSION_PLAN_DELETE, Some(wire_params)) .await?; - Ok(serde_json::from_value(_value)?) + Ok(()) } } -/// `session.name.*` RPCs. +/// `session.plugins.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcName<'a> { +pub struct SessionRpcPlugins<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcName<'a> { - /// Gets the session's friendly name. +impl<'a> SessionRpcPlugins<'a> { + /// Lists plugins installed for the session. /// - /// Wire method: `session.name.get`. + /// Wire method: `session.plugins.list`. /// /// # Returns /// - /// The session's friendly name, or null when not yet set. - pub async fn get(&self) -> Result { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); - let _value = self - .session - .client() - .call(rpc_methods::SESSION_NAME_GET, Some(wire_params)) - .await?; - Ok(serde_json::from_value(_value)?) - } - - /// Sets the session's friendly name. + /// Plugins installed for the session, with their enabled state and version metadata. /// - /// Wire method: `session.name.set`. + ///
/// - /// # Parameters + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. /// - /// * `params` - New friendly name to apply to the session. - pub async fn set(&self, params: NameSetRequest) -> Result<(), Error> { - let mut wire_params = serde_json::to_value(params)?; - wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_NAME_SET, Some(wire_params)) + .call(rpc_methods::SESSION_PLUGINS_LIST, Some(wire_params)) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } } -/// `session.permissions.*` RPCs. +/// `session.queue.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcPermissions<'a> { +pub struct SessionRpcQueue<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcPermissions<'a> { - /// Provides a decision for a pending tool permission request. +impl<'a> SessionRpcQueue<'a> { + /// Returns the local session's pending user-facing queued items and steering messages. /// - /// Wire method: `session.permissions.handlePendingPermissionRequest`. + /// Wire method: `session.queue.pendingItems`. /// - /// # Parameters + /// # Returns /// - /// * `params` - Pending permission request ID and the decision to apply (approve/reject and scope). + /// Snapshot of the session's pending queued items and immediate-steering messages. /// - /// # Returns + ///
/// - /// Indicates whether the permission decision was applied; false when the request was already resolved. - pub async fn handle_pending_permission_request( - &self, - params: PermissionDecisionRequest, - ) -> Result { - let mut wire_params = serde_json::to_value(params)?; - wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn pending_items(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call( - rpc_methods::SESSION_PERMISSIONS_HANDLEPENDINGPERMISSIONREQUEST, - Some(wire_params), - ) + .call(rpc_methods::SESSION_QUEUE_PENDINGITEMS, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Enables or disables automatic approval of tool permission requests for the session. + /// Removes the most recently queued user-facing item (LIFO). /// - /// Wire method: `session.permissions.setApproveAll`. + /// Wire method: `session.queue.removeMostRecent`. /// - /// # Parameters + /// # Returns /// - /// * `params` - Whether to auto-approve all tool permission requests for the rest of the session. + /// Indicates whether a user-facing pending item was removed. /// - /// # Returns + ///
/// - /// Indicates whether the operation succeeded. - pub async fn set_approve_all( - &self, - params: PermissionsSetApproveAllRequest, - ) -> Result { - let mut wire_params = serde_json::to_value(params)?; - wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn remove_most_recent(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() .call( - rpc_methods::SESSION_PERMISSIONS_SETAPPROVEALL, + rpc_methods::SESSION_QUEUE_REMOVEMOSTRECENT, Some(wire_params), ) .await?; Ok(serde_json::from_value(_value)?) } - /// Clears session-scoped tool permission approvals. + /// Clears all pending queued items on the local session. /// - /// Wire method: `session.permissions.resetSessionApprovals`. + /// Wire method: `session.queue.clear`. /// - /// # Returns + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. /// - /// Indicates whether the operation succeeded. - pub async fn reset_session_approvals( - &self, - ) -> Result { + ///
+ pub async fn clear(&self) -> Result<(), Error> { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call( - rpc_methods::SESSION_PERMISSIONS_RESETSESSIONAPPROVALS, - Some(wire_params), - ) + .call(rpc_methods::SESSION_QUEUE_CLEAR, Some(wire_params)) .await?; - Ok(serde_json::from_value(_value)?) + Ok(()) } } -/// `session.plan.*` RPCs. +/// `session.remote.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcPlan<'a> { +pub struct SessionRpcRemote<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcPlan<'a> { - /// Reads the session plan file from the workspace. +impl<'a> SessionRpcRemote<'a> { + /// Enables remote session export or steering. /// - /// Wire method: `session.plan.read`. + /// Wire method: `session.remote.enable`. + /// + /// # Parameters + /// + /// * `params` - Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. /// /// # Returns /// - /// Existence, contents, and resolved path of the session plan file. - pub async fn read(&self) -> Result { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); - let _value = self - .session - .client() - .call(rpc_methods::SESSION_PLAN_READ, Some(wire_params)) - .await?; - Ok(serde_json::from_value(_value)?) - } - - /// Writes new content to the session plan file. + /// GitHub URL for the session and a flag indicating whether remote steering is enabled. /// - /// Wire method: `session.plan.update`. + ///
/// - /// # Parameters + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. /// - /// * `params` - Replacement contents to write to the session plan file. - pub async fn update(&self, params: PlanUpdateRequest) -> Result<(), Error> { + ///
+ pub async fn enable(&self, params: RemoteEnableRequest) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_PLAN_UPDATE, Some(wire_params)) + .call(rpc_methods::SESSION_REMOTE_ENABLE, Some(wire_params)) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } - /// Deletes the session plan file from the workspace. + /// Disables remote session export and steering. /// - /// Wire method: `session.plan.delete`. - pub async fn delete(&self) -> Result<(), Error> { + /// Wire method: `session.remote.disable`. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn disable(&self) -> Result<(), Error> { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_PLAN_DELETE, Some(wire_params)) + .call(rpc_methods::SESSION_REMOTE_DISABLE, Some(wire_params)) .await?; Ok(()) } -} - -/// `session.plugins.*` RPCs. -#[derive(Clone, Copy)] -pub struct SessionRpcPlugins<'a> { - pub(crate) session: &'a Session, -} -impl<'a> SessionRpcPlugins<'a> { - /// Lists plugins installed for the session. + /// Persists a remote-steerability change emitted by the host as a session event. /// - /// Wire method: `session.plugins.list`. + /// Wire method: `session.remote.notifySteerableChanged`. + /// + /// # Parameters + /// + /// * `params` - New remote-steerability state to persist as a `session.remote_steerable_changed` event. /// /// # Returns /// - /// Plugins installed for the session, with their enabled state and version metadata. + /// Persist a steerability change as a `session.remote_steerable_changed` event. Used by the host (CLI / SDK consumer) when it has just finished enabling or disabling steering on a remote exporter that the runtime does not directly own. /// ///
/// @@ -1707,35 +3609,38 @@ impl<'a> SessionRpcPlugins<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn list(&self) -> Result { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + pub async fn notify_steerable_changed( + &self, + params: RemoteNotifySteerableChangedRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_PLUGINS_LIST, Some(wire_params)) + .call( + rpc_methods::SESSION_REMOTE_NOTIFYSTEERABLECHANGED, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } } -/// `session.remote.*` RPCs. +/// `session.schedule.*` RPCs. #[derive(Clone, Copy)] -pub struct SessionRpcRemote<'a> { +pub struct SessionRpcSchedule<'a> { pub(crate) session: &'a Session, } -impl<'a> SessionRpcRemote<'a> { - /// Enables remote session export or steering. +impl<'a> SessionRpcSchedule<'a> { + /// Lists the session's currently active scheduled prompts. /// - /// Wire method: `session.remote.enable`. - /// - /// # Parameters - /// - /// * `params` - Optional remote session mode ("off", "export", or "on"); defaults to enabling both export and remote steering. + /// Wire method: `session.schedule.list`. /// /// # Returns /// - /// GitHub URL for the session and a flag indicating whether remote steering is enabled. + /// Snapshot of the currently active recurring prompts for this session. /// ///
/// @@ -1744,20 +3649,27 @@ impl<'a> SessionRpcRemote<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn enable(&self, params: RemoteEnableRequest) -> Result { - let mut wire_params = serde_json::to_value(params)?; - wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_REMOTE_ENABLE, Some(wire_params)) + .call(rpc_methods::SESSION_SCHEDULE_LIST, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Disables remote session export and steering. + /// Removes a scheduled prompt by id. /// - /// Wire method: `session.remote.disable`. + /// Wire method: `session.schedule.stop`. + /// + /// # Parameters + /// + /// * `params` - Identifier of the scheduled prompt to remove. + /// + /// # Returns + /// + /// Remove a scheduled prompt by id. The result entry is omitted if the id was unknown. /// ///
/// @@ -1766,14 +3678,15 @@ impl<'a> SessionRpcRemote<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn disable(&self) -> Result<(), Error> { - let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + pub async fn stop(&self, params: ScheduleStopRequest) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_REMOTE_DISABLE, Some(wire_params)) + .call(rpc_methods::SESSION_SCHEDULE_STOP, Some(wire_params)) .await?; - Ok(()) + Ok(serde_json::from_value(_value)?) } } @@ -1861,6 +3774,31 @@ impl<'a> SessionRpcSkills<'a> { Ok(serde_json::from_value(_value)?) } + /// Returns the skills that have been invoked during this session. + /// + /// Wire method: `session.skills.getInvoked`. + /// + /// # Returns + /// + /// Skills invoked during this session, ordered by invocation time (most recent last). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn get_invoked(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_SKILLS_GETINVOKED, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + /// Enables a skill for the session. /// /// Wire method: `session.skills.enable`. @@ -1937,6 +3875,27 @@ impl<'a> SessionRpcSkills<'a> { .await?; Ok(serde_json::from_value(_value)?) } + + /// Ensures the session's skill definitions have been loaded from disk. + /// + /// Wire method: `session.skills.ensureLoaded`. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn ensure_loaded(&self) -> Result<(), Error> { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_SKILLS_ENSURELOADED, Some(wire_params)) + .await?; + Ok(()) + } } /// `session.tasks.*` RPCs. @@ -1948,15 +3907,123 @@ pub struct SessionRpcTasks<'a> { impl<'a> SessionRpcTasks<'a> { /// Starts a background agent task in the session. /// - /// Wire method: `session.tasks.startAgent`. + /// Wire method: `session.tasks.startAgent`. + /// + /// # Parameters + /// + /// * `params` - Agent type, prompt, name, and optional description and model override for the new task. + /// + /// # Returns + /// + /// Identifier assigned to the newly started background agent task. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn start_agent( + &self, + params: TasksStartAgentRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_TASKS_STARTAGENT, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Lists background tasks tracked by the session. + /// + /// Wire method: `session.tasks.list`. + /// + /// # Returns + /// + /// Background tasks currently tracked by the session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn list(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_TASKS_LIST, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Refreshes metadata for any detached background shells the runtime knows about. + /// + /// Wire method: `session.tasks.refresh`. + /// + /// # Returns + /// + /// Refresh metadata for any detached background shells the runtime knows about. Use after a long pause to pick up exit/output state for shells running outside the agent loop. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn refresh(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_TASKS_REFRESH, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Waits for all in-flight background tasks and any follow-up turns to settle. + /// + /// Wire method: `session.tasks.waitForPending`. + /// + /// # Returns + /// + /// Wait until all in-flight background tasks (agents + shells) and any follow-up turns scheduled by their completions have settled. Returns when the runtime is fully drained or after an internal timeout (default 10 minutes; configurable via COPILOT_TASK_WAIT_TIMEOUT_SECONDS). + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn wait_for_pending(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call(rpc_methods::SESSION_TASKS_WAITFORPENDING, Some(wire_params)) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Returns progress information for a background task by ID. + /// + /// Wire method: `session.tasks.getProgress`. /// /// # Parameters /// - /// * `params` - Agent type, prompt, name, and optional description and model override for the new task. + /// * `params` - Identifier of the background task to fetch progress for. /// /// # Returns /// - /// Identifier assigned to the newly started background agent task. + /// Progress information for the task, or null when no task with that ID is tracked. /// ///
/// @@ -1965,27 +4032,27 @@ impl<'a> SessionRpcTasks<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn start_agent( + pub async fn get_progress( &self, - params: TasksStartAgentRequest, - ) -> Result { + params: TasksGetProgressRequest, + ) -> Result { let mut wire_params = serde_json::to_value(params)?; wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); let _value = self .session .client() - .call(rpc_methods::SESSION_TASKS_STARTAGENT, Some(wire_params)) + .call(rpc_methods::SESSION_TASKS_GETPROGRESS, Some(wire_params)) .await?; Ok(serde_json::from_value(_value)?) } - /// Lists background tasks tracked by the session. + /// Returns the first sync-waiting task that can currently be promoted to background mode. /// - /// Wire method: `session.tasks.list`. + /// Wire method: `session.tasks.getCurrentPromotable`. /// /// # Returns /// - /// Background tasks currently tracked by the session. + /// The first sync-waiting task that can currently be promoted to background mode. /// ///
/// @@ -1994,12 +4061,15 @@ impl<'a> SessionRpcTasks<'a> { /// SDK and CLI versions if your code depends on it. /// ///
- pub async fn list(&self) -> Result { + pub async fn get_current_promotable(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self .session .client() - .call(rpc_methods::SESSION_TASKS_LIST, Some(wire_params)) + .call( + rpc_methods::SESSION_TASKS_GETCURRENTPROMOTABLE, + Some(wire_params), + ) .await?; Ok(serde_json::from_value(_value)?) } @@ -2040,6 +4110,36 @@ impl<'a> SessionRpcTasks<'a> { Ok(serde_json::from_value(_value)?) } + /// Atomically promotes the first promotable sync-waiting task to background mode and returns it. + /// + /// Wire method: `session.tasks.promoteCurrentToBackground`. + /// + /// # Returns + /// + /// The promoted task as it now exists in background mode, omitted if no promotable task was waiting. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn promote_current_to_background( + &self, + ) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_TASKS_PROMOTECURRENTTOBACKGROUND, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + /// Cancels a background task. /// /// Wire method: `session.tasks.cancel`. @@ -2134,6 +4234,46 @@ impl<'a> SessionRpcTasks<'a> { } } +/// `session.telemetry.*` RPCs. +#[derive(Clone, Copy)] +pub struct SessionRpcTelemetry<'a> { + pub(crate) session: &'a Session, +} + +impl<'a> SessionRpcTelemetry<'a> { + /// Sets feature override key/value pairs to attach to subsequent telemetry events for the session. + /// + /// Wire method: `session.telemetry.setFeatureOverrides`. + /// + /// # Parameters + /// + /// * `params` - Feature override key/value pairs to attach to subsequent telemetry events from this session. + /// + ///
+ /// + /// **Experimental.** This API is part of an experimental wire-protocol surface + /// and may change or be removed in future SDK or CLI releases. Pin both the + /// SDK and CLI versions if your code depends on it. + /// + ///
+ pub async fn set_feature_overrides( + &self, + params: TelemetrySetFeatureOverridesRequest, + ) -> Result<(), Error> { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_TELEMETRY_SETFEATUREOVERRIDES, + Some(wire_params), + ) + .await?; + Ok(()) + } +} + /// `session.tools.*` RPCs. #[derive(Clone, Copy)] pub struct SessionRpcTools<'a> { @@ -2168,6 +4308,26 @@ impl<'a> SessionRpcTools<'a> { .await?; Ok(serde_json::from_value(_value)?) } + + /// Resolves, builds, and validates the runtime tool list for the session. + /// + /// Wire method: `session.tools.initializeAndValidate`. + /// + /// # Returns + /// + /// Resolve, build, and validate the runtime tool list for this session. Subagent sessions and consumer flows that need an initialized tool set before `send` invoke this. Default base-class implementation is a no-op for sessions that don't support tool validation. + pub async fn initialize_and_validate(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_TOOLS_INITIALIZEANDVALIDATE, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } } /// `session.ui.*` RPCs. @@ -2229,6 +4389,168 @@ impl<'a> SessionRpcUi<'a> { .await?; Ok(serde_json::from_value(_value)?) } + + /// Resolves a pending `user_input.requested` event with the user's response. + /// + /// Wire method: `session.ui.handlePendingUserInput`. + /// + /// # Parameters + /// + /// * `params` - Request ID of a pending `user_input.requested` event and the user's response. + /// + /// # Returns + /// + /// Indicates whether the pending UI request was resolved by this call. + pub async fn handle_pending_user_input( + &self, + params: UIHandlePendingUserInputRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_HANDLEPENDINGUSERINPUT, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Resolves a pending `sampling.requested` event with a sampling result, or rejects it. + /// + /// Wire method: `session.ui.handlePendingSampling`. + /// + /// # Parameters + /// + /// * `params` - Request ID of a pending `sampling.requested` event and an optional sampling result payload (omit to reject). + /// + /// # Returns + /// + /// Indicates whether the pending UI request was resolved by this call. + pub async fn handle_pending_sampling( + &self, + params: UIHandlePendingSamplingRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_HANDLEPENDINGSAMPLING, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Resolves a pending `auto_mode_switch.requested` event with the user's accept/decline decision. + /// + /// Wire method: `session.ui.handlePendingAutoModeSwitch`. + /// + /// # Parameters + /// + /// * `params` - Request ID of a pending `auto_mode_switch.requested` event and the user's response. + /// + /// # Returns + /// + /// Indicates whether the pending UI request was resolved by this call. + pub async fn handle_pending_auto_mode_switch( + &self, + params: UIHandlePendingAutoModeSwitchRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_HANDLEPENDINGAUTOMODESWITCH, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Resolves a pending `exit_plan_mode.requested` event with the user's response. + /// + /// Wire method: `session.ui.handlePendingExitPlanMode`. + /// + /// # Parameters + /// + /// * `params` - Request ID of a pending `exit_plan_mode.requested` event and the user's response. + /// + /// # Returns + /// + /// Indicates whether the pending UI request was resolved by this call. + pub async fn handle_pending_exit_plan_mode( + &self, + params: UIHandlePendingExitPlanModeRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_HANDLEPENDINGEXITPLANMODE, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Registers an in-process handler for auto-mode-switch requests so the server bridge skips dispatch. + /// + /// Wire method: `session.ui.registerDirectAutoModeSwitchHandler`. + /// + /// # Returns + /// + /// Register an in-process handler for `auto_mode_switch.requested` events. The caller still attaches the actual listener via the standard event-subscription mechanism; this registration solely tells the server bridge to skip its own dispatch (so a remote client doesn't race the in-process handler for the same requestId). + pub async fn register_direct_auto_mode_switch_handler( + &self, + ) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_REGISTERDIRECTAUTOMODESWITCHHANDLER, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Unregisters a previously-registered in-process auto-mode-switch handler by its opaque handle. + /// + /// Wire method: `session.ui.unregisterDirectAutoModeSwitchHandler`. + /// + /// # Parameters + /// + /// * `params` - Opaque handle previously returned by `registerDirectAutoModeSwitchHandler` to release. + /// + /// # Returns + /// + /// Indicates whether the handle was active and the registration count was decremented. + pub async fn unregister_direct_auto_mode_switch_handler( + &self, + params: UIUnregisterDirectAutoModeSwitchHandlerRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_UI_UNREGISTERDIRECTAUTOMODESWITCHHANDLER, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } } /// `session.usage.*` RPCs. @@ -2277,7 +4599,7 @@ impl<'a> SessionRpcWorkspaces<'a> { /// /// # Returns /// - /// Current workspace metadata for the session, or null when not available. + /// Current workspace metadata for the session, including its absolute filesystem path when available. pub async fn get_workspace(&self) -> Result { let wire_params = serde_json::json!({ "sessionId": self.session.id() }); let _value = self @@ -2353,4 +4675,80 @@ impl<'a> SessionRpcWorkspaces<'a> { .await?; Ok(()) } + + /// Lists workspace checkpoints in chronological order. + /// + /// Wire method: `session.workspaces.listCheckpoints`. + /// + /// # Returns + /// + /// Workspace checkpoints in chronological order; empty when the workspace is not enabled. + pub async fn list_checkpoints(&self) -> Result { + let wire_params = serde_json::json!({ "sessionId": self.session.id() }); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_WORKSPACES_LISTCHECKPOINTS, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Reads the content of a workspace checkpoint by number. + /// + /// Wire method: `session.workspaces.readCheckpoint`. + /// + /// # Parameters + /// + /// * `params` - Checkpoint number to read. + /// + /// # Returns + /// + /// Checkpoint content as a UTF-8 string, or null when the checkpoint or workspace is missing. + pub async fn read_checkpoint( + &self, + params: WorkspacesReadCheckpointRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_WORKSPACES_READCHECKPOINT, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } + + /// Saves pasted content as a UTF-8 file in the session workspace. + /// + /// Wire method: `session.workspaces.saveLargePaste`. + /// + /// # Parameters + /// + /// * `params` - Pasted content to save as a UTF-8 file in the session workspace. + /// + /// # Returns + /// + /// Descriptor for the saved paste file, or null when the workspace is unavailable. + pub async fn save_large_paste( + &self, + params: WorkspacesSaveLargePasteRequest, + ) -> Result { + let mut wire_params = serde_json::to_value(params)?; + wire_params["sessionId"] = serde_json::Value::String(self.session.id().to_string()); + let _value = self + .session + .client() + .call( + rpc_methods::SESSION_WORKSPACES_SAVELARGEPASTE, + Some(wire_params), + ) + .await?; + Ok(serde_json::from_value(_value)?) + } } diff --git a/rust/src/generated/session_events.rs b/rust/src/generated/session_events.rs index 459c03b77..a3b307984 100644 --- a/rust/src/generated/session_events.rs +++ b/rust/src/generated/session_events.rs @@ -437,7 +437,7 @@ pub struct SessionStartData { /// ISO 8601 timestamp when the session was created pub start_time: String, /// Schema version number for the session event format - pub version: f64, + pub version: i64, } /// Session event "session.resume". Session resume metadata including current context and event count @@ -454,7 +454,7 @@ pub struct SessionResumeData { #[serde(skip_serializing_if = "Option::is_none")] pub continue_pending_work: Option, /// Total number of persisted events in the session at the time of resume - pub event_count: f64, + pub event_count: i64, /// Reasoning effort level used for model calls, if applicable (e.g. "none", "low", "medium", "high", "xhigh", "max") #[serde(skip_serializing_if = "Option::is_none")] pub reasoning_effort: Option, @@ -504,7 +504,7 @@ pub struct SessionErrorData { pub stack: Option, /// HTTP status code from the upstream request, if applicable #[serde(skip_serializing_if = "Option::is_none")] - pub status_code: Option, + pub status_code: Option, /// Optional URL associated with this error that the user can open in a browser #[serde(skip_serializing_if = "Option::is_none")] pub url: Option, @@ -679,21 +679,21 @@ pub struct SessionHandoffData { #[serde(rename_all = "camelCase")] pub struct SessionTruncationData { /// Number of messages removed by truncation - pub messages_removed_during_truncation: f64, + pub messages_removed_during_truncation: i64, /// Identifier of the component that performed truncation (e.g., "BasicTruncator") pub performed_by: String, /// Number of conversation messages after truncation - pub post_truncation_messages_length: f64, + pub post_truncation_messages_length: i64, /// Total tokens in conversation messages after truncation - pub post_truncation_tokens_in_messages: f64, + pub post_truncation_tokens_in_messages: i64, /// Number of conversation messages before truncation - pub pre_truncation_messages_length: f64, + pub pre_truncation_messages_length: i64, /// Total tokens in conversation messages before truncation - pub pre_truncation_tokens_in_messages: f64, + pub pre_truncation_tokens_in_messages: i64, /// Maximum token count for the model's context window - pub token_limit: f64, + pub token_limit: i64, /// Number of tokens removed by truncation - pub tokens_removed_during_truncation: f64, + pub tokens_removed_during_truncation: i64, } /// Session event "session.snapshot_rewind". Session rewind details including target event and count of removed events @@ -701,7 +701,7 @@ pub struct SessionTruncationData { #[serde(rename_all = "camelCase")] pub struct SessionSnapshotRewindData { /// Number of events that were removed by the rewind - pub events_removed: f64, + pub events_removed: i64, /// Event ID that was rewound to; this event and all after it were removed pub up_to_event_id: String, } @@ -713,9 +713,9 @@ pub struct ShutdownCodeChanges { /// List of file paths that were modified during the session pub files_modified: Vec, /// Total number of lines added during the session - pub lines_added: f64, + pub lines_added: i64, /// Total number of lines removed during the session - pub lines_removed: f64, + pub lines_removed: i64, } /// Request count and cost metrics @@ -725,7 +725,7 @@ pub struct ShutdownModelMetricRequests { /// Cumulative cost multiplier for requests to this model pub cost: f64, /// Total number of API requests made to this model - pub count: f64, + pub count: i64, } /// Schema for the `ShutdownModelMetricTokenDetail` type. @@ -733,7 +733,7 @@ pub struct ShutdownModelMetricRequests { #[serde(rename_all = "camelCase")] pub struct ShutdownModelMetricTokenDetail { /// Accumulated token count for this token type - pub token_count: f64, + pub token_count: i64, } /// Token usage breakdown @@ -741,16 +741,16 @@ pub struct ShutdownModelMetricTokenDetail { #[serde(rename_all = "camelCase")] pub struct ShutdownModelMetricUsage { /// Total tokens read from prompt cache across all requests - pub cache_read_tokens: f64, + pub cache_read_tokens: i64, /// Total tokens written to prompt cache across all requests - pub cache_write_tokens: f64, + pub cache_write_tokens: i64, /// Total input tokens consumed across all requests to this model - pub input_tokens: f64, + pub input_tokens: i64, /// Total output tokens produced across all requests to this model - pub output_tokens: f64, + pub output_tokens: i64, /// Total reasoning tokens produced across all requests to this model #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning_tokens: Option, + pub reasoning_tokens: Option, } /// Schema for the `ShutdownModelMetric` type. @@ -764,7 +764,7 @@ pub struct ShutdownModelMetric { pub token_details: HashMap, /// Accumulated nano-AI units cost for this model #[serde(skip_serializing_if = "Option::is_none")] - pub total_nano_aiu: Option, + pub total_nano_aiu: Option, /// Token usage breakdown pub usage: ShutdownModelMetricUsage, } @@ -774,7 +774,7 @@ pub struct ShutdownModelMetric { #[serde(rename_all = "camelCase")] pub struct ShutdownTokenDetail { /// Accumulated token count for this token type - pub token_count: f64, + pub token_count: i64, } /// Session event "session.shutdown". Session termination metrics including usage statistics, code changes, and shutdown reason @@ -785,38 +785,38 @@ pub struct SessionShutdownData { pub code_changes: ShutdownCodeChanges, /// Non-system message token count at shutdown #[serde(skip_serializing_if = "Option::is_none")] - pub conversation_tokens: Option, + pub conversation_tokens: Option, /// Model that was selected at the time of shutdown #[serde(skip_serializing_if = "Option::is_none")] pub current_model: Option, /// Total tokens in context window at shutdown #[serde(skip_serializing_if = "Option::is_none")] - pub current_tokens: Option, + pub current_tokens: Option, /// Error description when shutdownType is "error" #[serde(skip_serializing_if = "Option::is_none")] pub error_reason: Option, /// Per-model usage breakdown, keyed by model identifier pub model_metrics: HashMap, /// Unix timestamp (milliseconds) when the session started - pub session_start_time: f64, + pub session_start_time: i64, /// Whether the session ended normally ("routine") or due to a crash/fatal error ("error") pub shutdown_type: ShutdownType, /// System message token count at shutdown #[serde(skip_serializing_if = "Option::is_none")] - pub system_tokens: Option, + pub system_tokens: Option, /// Session-wide per-token-type accumulated token counts #[serde(default)] pub token_details: HashMap, /// Tool definitions token count at shutdown #[serde(skip_serializing_if = "Option::is_none")] - pub tool_definitions_tokens: Option, + pub tool_definitions_tokens: Option, /// Cumulative time spent in API calls during the session, in milliseconds - pub total_api_duration_ms: f64, + pub total_api_duration_ms: i64, /// Session-wide accumulated nano-AI units cost #[serde(skip_serializing_if = "Option::is_none")] - pub total_nano_aiu: Option, + pub total_nano_aiu: Option, /// Total number of premium API requests used during the session - pub total_premium_requests: f64, + pub total_premium_requests: i64, } /// Session event "session.context_changed". Updated working directory and git context after the change @@ -854,22 +854,22 @@ pub struct SessionContextChangedData { pub struct SessionUsageInfoData { /// Token count from non-system messages (user, assistant, tool) #[serde(skip_serializing_if = "Option::is_none")] - pub conversation_tokens: Option, + pub conversation_tokens: Option, /// Current number of tokens in the context window - pub current_tokens: f64, + pub current_tokens: i64, /// Whether this is the first usage_info event emitted in this session #[serde(skip_serializing_if = "Option::is_none")] pub is_initial: Option, /// Current number of messages in the conversation - pub messages_length: f64, + pub messages_length: i64, /// Token count from system message(s) #[serde(skip_serializing_if = "Option::is_none")] - pub system_tokens: Option, + pub system_tokens: Option, /// Maximum token count for the model's context window - pub token_limit: f64, + pub token_limit: i64, /// Token count from tool definitions #[serde(skip_serializing_if = "Option::is_none")] - pub tool_definitions_tokens: Option, + pub tool_definitions_tokens: Option, } /// Session event "session.compaction_start". Context window breakdown at the start of LLM-powered conversation compaction @@ -878,13 +878,13 @@ pub struct SessionUsageInfoData { pub struct SessionCompactionStartData { /// Token count from non-system messages (user, assistant, tool) at compaction start #[serde(skip_serializing_if = "Option::is_none")] - pub conversation_tokens: Option, + pub conversation_tokens: Option, /// Token count from system message(s) at compaction start #[serde(skip_serializing_if = "Option::is_none")] - pub system_tokens: Option, + pub system_tokens: Option, /// Token count from tool definitions at compaction start #[serde(skip_serializing_if = "Option::is_none")] - pub tool_definitions_tokens: Option, + pub tool_definitions_tokens: Option, } /// Token usage detail for a single billing category @@ -892,11 +892,11 @@ pub struct SessionCompactionStartData { #[serde(rename_all = "camelCase")] pub struct CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail { /// Number of tokens in this billing batch - pub batch_size: f64, + pub batch_size: i64, /// Cost per batch of tokens - pub cost_per_batch: f64, + pub cost_per_batch: i64, /// Total token count for this entry - pub token_count: f64, + pub token_count: i64, /// Token category (e.g., "input", "output") pub token_type: String, } @@ -908,7 +908,7 @@ pub struct CompactionCompleteCompactionTokensUsedCopilotUsage { /// Itemized token usage breakdown pub token_details: Vec, /// Total cost in nano-AI units for this request - pub total_nano_aiu: f64, + pub total_nano_aiu: i64, } /// Token usage breakdown for the compaction LLM call (aligned with assistant.usage format) @@ -917,25 +917,25 @@ pub struct CompactionCompleteCompactionTokensUsedCopilotUsage { pub struct CompactionCompleteCompactionTokensUsed { /// Cached input tokens reused in the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] - pub cache_read_tokens: Option, + pub cache_read_tokens: Option, /// Tokens written to prompt cache in the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] - pub cache_write_tokens: Option, + pub cache_write_tokens: Option, /// Per-request cost and usage data from the CAPI copilot_usage response field #[serde(skip_serializing_if = "Option::is_none")] pub copilot_usage: Option, /// Duration of the compaction LLM call in milliseconds #[serde(skip_serializing_if = "Option::is_none")] - pub duration: Option, + pub duration: Option, /// Input tokens consumed by the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] - pub input_tokens: Option, + pub input_tokens: Option, /// Model identifier used for the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] pub model: Option, /// Output tokens produced by the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] - pub output_tokens: Option, + pub output_tokens: Option, } /// Session event "session.compaction_complete". Conversation compaction results including success status, metrics, and optional error details @@ -944,7 +944,7 @@ pub struct CompactionCompleteCompactionTokensUsed { pub struct SessionCompactionCompleteData { /// Checkpoint snapshot number created for recovery #[serde(skip_serializing_if = "Option::is_none")] - pub checkpoint_number: Option, + pub checkpoint_number: Option, /// File path where the checkpoint was stored #[serde(skip_serializing_if = "Option::is_none")] pub checkpoint_path: Option, @@ -953,22 +953,22 @@ pub struct SessionCompactionCompleteData { pub compaction_tokens_used: Option, /// Token count from non-system messages (user, assistant, tool) after compaction #[serde(skip_serializing_if = "Option::is_none")] - pub conversation_tokens: Option, + pub conversation_tokens: Option, /// Error message if compaction failed #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, /// Number of messages removed during compaction #[serde(skip_serializing_if = "Option::is_none")] - pub messages_removed: Option, + pub messages_removed: Option, /// Total tokens in conversation after compaction #[serde(skip_serializing_if = "Option::is_none")] - pub post_compaction_tokens: Option, + pub post_compaction_tokens: Option, /// Number of messages before compaction #[serde(skip_serializing_if = "Option::is_none")] - pub pre_compaction_messages_length: Option, + pub pre_compaction_messages_length: Option, /// Total tokens in conversation before compaction #[serde(skip_serializing_if = "Option::is_none")] - pub pre_compaction_tokens: Option, + pub pre_compaction_tokens: Option, /// GitHub request tracing ID (x-github-request-id header) for the compaction LLM call #[serde(skip_serializing_if = "Option::is_none")] pub request_id: Option, @@ -979,13 +979,13 @@ pub struct SessionCompactionCompleteData { pub summary_content: Option, /// Token count from system message(s) after compaction #[serde(skip_serializing_if = "Option::is_none")] - pub system_tokens: Option, + pub system_tokens: Option, /// Number of tokens removed during compaction #[serde(skip_serializing_if = "Option::is_none")] - pub tokens_removed: Option, + pub tokens_removed: Option, /// Token count from tool definitions after compaction #[serde(skip_serializing_if = "Option::is_none")] - pub tool_definitions_tokens: Option, + pub tool_definitions_tokens: Option, } /// Session event "session.task_complete". Task completion notification with summary from the agent @@ -1018,7 +1018,7 @@ pub struct UserMessageData { /// True when this user message was auto-injected by autopilot's continuation loop rather than typed by the user; used to distinguish autopilot-driven turns in telemetry. #[serde(skip_serializing_if = "Option::is_none")] pub is_autopilot_continuation: Option, - /// Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit + /// Path-backed native document attachments that stayed on the tagged_files path flow because native upload could not read them or would exceed the request size limit #[serde(default)] pub native_document_path_fallback_paths: Vec, /// Parent agent task ID for background telemetry correlated to this user turn @@ -1084,7 +1084,7 @@ pub struct AssistantReasoningDeltaData { #[serde(rename_all = "camelCase")] pub struct AssistantStreamingDeltaData { /// Cumulative total bytes received from the streaming response so far - pub total_response_size_bytes: f64, + pub total_response_size_bytes: i64, } /// A tool invocation request from the assistant @@ -1140,7 +1140,7 @@ pub struct AssistantMessageData { pub model: Option, /// Actual output token count from the API response (completion_tokens), used for accurate token accounting #[serde(skip_serializing_if = "Option::is_none")] - pub output_tokens: Option, + pub output_tokens: Option, /// Tool call ID of the parent tool invocation when this event originates from a sub-agent #[doc(hidden)] #[deprecated] @@ -1205,11 +1205,11 @@ pub struct AssistantTurnEndData { #[serde(rename_all = "camelCase")] pub struct AssistantUsageCopilotUsageTokenDetail { /// Number of tokens in this billing batch - pub batch_size: f64, + pub batch_size: i64, /// Cost per batch of tokens - pub cost_per_batch: f64, + pub cost_per_batch: i64, /// Total token count for this entry - pub token_count: f64, + pub token_count: i64, /// Token category (e.g., "input", "output") pub token_type: String, } @@ -1221,7 +1221,7 @@ pub struct AssistantUsageCopilotUsage { /// Itemized token usage breakdown pub token_details: Vec, /// Total cost in nano-AI units for this request - pub total_nano_aiu: f64, + pub total_nano_aiu: i64, } /// Schema for the `AssistantUsageQuotaSnapshot` type. @@ -1229,14 +1229,14 @@ pub struct AssistantUsageCopilotUsage { #[serde(rename_all = "camelCase")] pub struct AssistantUsageQuotaSnapshot { /// Total requests allowed by the entitlement - pub entitlement_requests: f64, + pub entitlement_requests: i64, /// Whether the user has an unlimited usage entitlement pub is_unlimited_entitlement: bool, /// Number of requests over the entitlement limit pub overage: f64, /// Whether overage is allowed when quota is exhausted pub overage_allowed_with_exhausted_quota: bool, - /// Percentage of quota remaining (0.0 to 1.0) + /// Percentage of quota remaining (0 to 100) pub remaining_percentage: f64, /// Date when the quota resets #[serde(skip_serializing_if = "Option::is_none")] @@ -1244,7 +1244,7 @@ pub struct AssistantUsageQuotaSnapshot { /// Whether usage is still permitted after quota exhaustion pub usage_allowed_with_exhausted_quota: bool, /// Number of requests already consumed - pub used_requests: f64, + pub used_requests: i64, } /// Session event "assistant.usage". LLM API call usage metrics including tokens, costs, quotas, and billing information @@ -1259,10 +1259,10 @@ pub struct AssistantUsageData { pub api_endpoint: Option, /// Number of tokens read from prompt cache #[serde(skip_serializing_if = "Option::is_none")] - pub cache_read_tokens: Option, + pub cache_read_tokens: Option, /// Number of tokens written to prompt cache #[serde(skip_serializing_if = "Option::is_none")] - pub cache_write_tokens: Option, + pub cache_write_tokens: Option, /// Per-request cost and usage data from the CAPI copilot_usage response field #[serde(skip_serializing_if = "Option::is_none")] pub copilot_usage: Option, @@ -1271,13 +1271,13 @@ pub struct AssistantUsageData { pub cost: Option, /// Duration of the API call in milliseconds #[serde(skip_serializing_if = "Option::is_none")] - pub duration: Option, + pub duration: Option, /// What initiated this API call (e.g., "sub-agent", "mcp-sampling"); absent for user-initiated calls #[serde(skip_serializing_if = "Option::is_none")] pub initiator: Option, /// Number of input tokens consumed #[serde(skip_serializing_if = "Option::is_none")] - pub input_tokens: Option, + pub input_tokens: Option, /// Average inter-token latency in milliseconds. Only available for streaming requests #[serde(skip_serializing_if = "Option::is_none")] pub inter_token_latency_ms: Option, @@ -1285,7 +1285,7 @@ pub struct AssistantUsageData { pub model: String, /// Number of output tokens produced #[serde(skip_serializing_if = "Option::is_none")] - pub output_tokens: Option, + pub output_tokens: Option, /// Parent tool call ID when this usage originates from a sub-agent #[doc(hidden)] #[deprecated] @@ -1302,10 +1302,10 @@ pub struct AssistantUsageData { pub reasoning_effort: Option, /// Number of output tokens used for reasoning (e.g., chain-of-thought) #[serde(skip_serializing_if = "Option::is_none")] - pub reasoning_tokens: Option, + pub reasoning_tokens: Option, /// Time to first token in milliseconds. Only available for streaming requests #[serde(skip_serializing_if = "Option::is_none")] - pub ttft_ms: Option, + pub ttft_ms: Option, } /// Session event "model.call_failure". Failed LLM API call metadata for telemetry @@ -1317,7 +1317,7 @@ pub struct ModelCallFailureData { pub api_call_id: Option, /// Duration of the failed API call in milliseconds #[serde(skip_serializing_if = "Option::is_none")] - pub duration_ms: Option, + pub duration_ms: Option, /// Raw provider/runtime error message for restricted telemetry #[serde(skip_serializing_if = "Option::is_none")] pub error_message: Option, @@ -1334,7 +1334,7 @@ pub struct ModelCallFailureData { pub source: ModelCallFailureSource, /// HTTP status code from the failed request #[serde(skip_serializing_if = "Option::is_none")] - pub status_code: Option, + pub status_code: Option, } /// Session event "abort". Turn abort information including the reason for termination @@ -1435,7 +1435,7 @@ pub struct ToolExecutionCompleteContentTerminal { pub cwd: Option, /// Process exit code, if the command has completed #[serde(skip_serializing_if = "Option::is_none")] - pub exit_code: Option, + pub exit_code: Option, /// Terminal/shell output text pub text: String, /// Content block type discriminator @@ -1500,7 +1500,7 @@ pub struct ToolExecutionCompleteContentResourceLink { pub name: String, /// Size of the resource in bytes #[serde(skip_serializing_if = "Option::is_none")] - pub size: Option, + pub size: Option, /// Human-readable display title for the resource #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, @@ -1647,7 +1647,7 @@ pub struct SubagentCompletedData { pub agent_name: String, /// Wall-clock duration of the sub-agent execution in milliseconds #[serde(skip_serializing_if = "Option::is_none")] - pub duration_ms: Option, + pub duration_ms: Option, /// Model used by the sub-agent #[serde(skip_serializing_if = "Option::is_none")] pub model: Option, @@ -1655,10 +1655,10 @@ pub struct SubagentCompletedData { pub tool_call_id: String, /// Total tokens (input + output) consumed by the sub-agent #[serde(skip_serializing_if = "Option::is_none")] - pub total_tokens: Option, + pub total_tokens: Option, /// Total number of tool calls made by the sub-agent #[serde(skip_serializing_if = "Option::is_none")] - pub total_tool_calls: Option, + pub total_tool_calls: Option, } /// Session event "subagent.failed". Sub-agent failure details including error message and agent information @@ -1671,7 +1671,7 @@ pub struct SubagentFailedData { pub agent_name: String, /// Wall-clock duration of the sub-agent execution in milliseconds #[serde(skip_serializing_if = "Option::is_none")] - pub duration_ms: Option, + pub duration_ms: Option, /// Error message describing why the sub-agent failed pub error: String, /// Model used by the sub-agent (if any model calls succeeded before failure) @@ -1681,10 +1681,10 @@ pub struct SubagentFailedData { pub tool_call_id: String, /// Total tokens (input + output) consumed before the sub-agent failed #[serde(skip_serializing_if = "Option::is_none")] - pub total_tokens: Option, + pub total_tokens: Option, /// Total number of tool calls made before the sub-agent failed #[serde(skip_serializing_if = "Option::is_none")] - pub total_tool_calls: Option, + pub total_tool_calls: Option, } /// Session event "subagent.selected". Custom agent selection details including name and available tools @@ -2343,7 +2343,7 @@ pub struct PermissionCancelled { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionRule { - /// Optional rule argument matched against the request + /// Argument value matched against the request, or null when the rule kind has no argument (e.g. 'read', 'write', 'memory'). pub argument: Option, /// The rule kind, such as Shell or GitHubMCP pub kind: String, @@ -2654,7 +2654,7 @@ pub struct AutoModeSwitchRequestedData { pub request_id: RequestId, /// Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt. #[serde(skip_serializing_if = "Option::is_none")] - pub retry_after_seconds: Option, + pub retry_after_seconds: Option, } /// Session event "auto_mode_switch.completed". Auto mode switch completion notification diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json index f61d4fb85..7938d3717 100644 --- a/test/harness/package-lock.json +++ b/test/harness/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@github/copilot": "^1.0.49", + "@github/copilot": "^1.0.51-1", "@modelcontextprotocol/sdk": "^1.26.0", "@types/node": "^25.3.3", "@types/node-forge": "^1.3.14", @@ -464,29 +464,29 @@ } }, "node_modules/@github/copilot": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.49.tgz", - "integrity": "sha512-40Udj9uCNXaVT2XYbB93CaA7P/rWdy7DP1r088t11s0chWfm5smm9RDMNRj2KqMywwYw3xgf3ZcTFoTLy7kleA==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.51-1.tgz", + "integrity": "sha512-TCPqoOAf0P6LUk3Xtp7hoO5d1AeGJQMA+Io6wxKeTNzZm6bWf41jFxQPs8Pnzua5vJwBjOid10XhGAVI5gHpFw==", "dev": true, "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "1.0.49", - "@github/copilot-darwin-x64": "1.0.49", - "@github/copilot-linux-arm64": "1.0.49", - "@github/copilot-linux-x64": "1.0.49", - "@github/copilot-linuxmusl-arm64": "1.0.49", - "@github/copilot-linuxmusl-x64": "1.0.49", - "@github/copilot-win32-arm64": "1.0.49", - "@github/copilot-win32-x64": "1.0.49" + "@github/copilot-darwin-arm64": "1.0.51-1", + "@github/copilot-darwin-x64": "1.0.51-1", + "@github/copilot-linux-arm64": "1.0.51-1", + "@github/copilot-linux-x64": "1.0.51-1", + "@github/copilot-linuxmusl-arm64": "1.0.51-1", + "@github/copilot-linuxmusl-x64": "1.0.51-1", + "@github/copilot-win32-arm64": "1.0.51-1", + "@github/copilot-win32-x64": "1.0.51-1" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.49.tgz", - "integrity": "sha512-b/qtH1ttG7dnoEC3gLDdrI9n7f5+3LEXD2rOvpdeoxoe8lDlSpUeF4AUpfh7kUivhCKlCIRV+H3+NcRX2rexuQ==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.51-1.tgz", + "integrity": "sha512-IRoWmK7ZGGmOceDpZ/jaGWJULGUVbF0hPuy5CaJsgEdtqD6K/0AfN2wPi+txuOo9H5Q4/iZTZFkoBC3W+moiXQ==", "cpu": [ "arm64" ], @@ -501,9 +501,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.49.tgz", - "integrity": "sha512-hHqoeCKqHttqtX3ZHj2TkAIX6jUg159tHDm7qVLccGotgz5bp6ywFxHyGYs7uwD0D90if/m+s87lXu2xAIkN9A==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.51-1.tgz", + "integrity": "sha512-tIesO+WWTnb5ZlE+l2uq8HNix5og/vV1JhsleXTDR18utVsgJ2Mf4a4nLIF4HXrKWOqJCSEtQHhBESKcOz1oUw==", "cpu": [ "x64" ], @@ -518,9 +518,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.49.tgz", - "integrity": "sha512-faNys7OcjoG6g2vlmOVLgzd4pZPmi0LpZJ0pnOLW6lJ2d9Lk5KsY3aX2g/Uqdoz9oqAPg64t8NH2WPSdHPmBTg==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.51-1.tgz", + "integrity": "sha512-yuiR663dZ28U6i7pKViVMvvJjznXGb8MW/Nw12jeW5Pu2iwnQyb5Mv8YrsrHNs/zSNX+dBkNHEy7sZd/MFkf+w==", "cpu": [ "arm64" ], @@ -535,9 +535,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.49.tgz", - "integrity": "sha512-bMqMoJ2r304yCmzZ+iv9Nf4xS4KdiqNZo+Ld7Iq9y5Rc5T+DVsrgISb9j2rBqtlOe0rdtKhwOuzSc4XP7BDcvw==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.51-1.tgz", + "integrity": "sha512-kx4NUR5qWj8lv+s+uCFQEiPLqddr/8a6ZAJe7h+ENGY/D9+TbP1pvK/nJ3Hjjy+tCpeIKS8+GJl8b1hfihAuXw==", "cpu": [ "x64" ], @@ -552,9 +552,9 @@ } }, "node_modules/@github/copilot-linuxmusl-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.49.tgz", - "integrity": "sha512-j2Ow72hiamC3yU1GQBl4WEAB9okuUxdGCs+bcYxtDSUY144F9i9U9WE8Oil3KP3Je+WLUZSf81OYsHTCM5OjbA==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.51-1.tgz", + "integrity": "sha512-2OijR/pU2U5sMSjntCwmQmdpGDawvT3jaIaEk9FMcCH2m5GJkQFe/WYCAYpoXPJARL/Y+QyY2yybUPUCyX3//A==", "cpu": [ "arm64" ], @@ -569,9 +569,9 @@ } }, "node_modules/@github/copilot-linuxmusl-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.49.tgz", - "integrity": "sha512-/a0iNVqXeEvvm0UyPMjW3UPl0meQSSd8SeaMYkkI2OQkYhlUrd9oaUEJzfYnBgPl37AK5+i73DFy09gSH+Efvw==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.51-1.tgz", + "integrity": "sha512-AHTZUgxzaKQF9XO2HQwwofooJzFLa0gJKN2pE0zCypmTgdyX/B6XV4GCWo3JqBZYwDG29+MtxM0KMDwvzGV3uw==", "cpu": [ "x64" ], @@ -586,9 +586,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.49.tgz", - "integrity": "sha512-2oaOoB47i2EcM1tSO+ay2X7xF29Yc/9LFOqkGZZrdS4gTQvTD3oITQBGwdj5CR3GN9pOFxWrhUvyDf9N77AHFg==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.51-1.tgz", + "integrity": "sha512-iyKSiUf+vj2M8D7WoIeu3QHuAuGCXvxYh8G0QT2CU/8LyLYcZUkGbQtPWqH4WJaSFrH6hCh4vHX8ATIv5ypnQA==", "cpu": [ "arm64" ], @@ -603,9 +603,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "1.0.49", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.49.tgz", - "integrity": "sha512-XwoiiCV3Q9PBV1eFNAag1KnIqN/cNDoNi2B6BJUkGPJUEW3AgrOABV6cmyZ3yEKUEXMZ78JIfS9kUEmTtCAY0g==", + "version": "1.0.51-1", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.51-1.tgz", + "integrity": "sha512-MrzXNjYTUbtiPReJfIOC55o1NDbRTTBubpiNBLit1q07QL8Q/ozp1NoNZ2p8z1u962lDDztPEPXlvs9dsq40VQ==", "cpu": [ "x64" ], diff --git a/test/harness/package.json b/test/harness/package.json index b9520b873..9668cd570 100644 --- a/test/harness/package.json +++ b/test/harness/package.json @@ -11,7 +11,7 @@ "test": "vitest run" }, "devDependencies": { - "@github/copilot": "^1.0.49", + "@github/copilot": "^1.0.51-1", "@modelcontextprotocol/sdk": "^1.26.0", "@types/node": "^25.3.3", "@types/node-forge": "^1.3.14", From 1f6a232acd426d117a07a16d3ca575f681c7aa32 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 22:18:28 -0400 Subject: [PATCH 2/6] Fix SDK codegen for Copilot 1.0.51-1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/Rpc.cs | 90 -------------- dotnet/src/Generated/SessionEvents.cs | 88 -------------- dotnet/src/Session.cs | 2 +- dotnet/test/E2E/ModeHandlersE2ETests.cs | 5 +- .../E2E/RpcAdditionalEdgeCasesE2ETests.cs | 2 +- dotnet/test/E2E/RpcServerE2ETests.cs | 2 +- dotnet/test/E2E/RpcSessionStateE2ETests.cs | 2 +- go/client.go | 2 +- go/internal/e2e/client_e2e_test.go | 8 +- go/internal/e2e/rpc_e2e_test.go | 4 +- .../e2e/rpc_event_side_effects_e2e_test.go | 2 +- go/internal/e2e/rpc_server_e2e_test.go | 4 +- go/internal/e2e/rpc_session_state_e2e_test.go | 4 +- go/internal/e2e/session_e2e_test.go | 2 +- go/session.go | 4 +- go/session_fs_provider.go | 6 +- go/types.go | 7 +- nodejs/src/generated/rpc.ts | 113 +++++++++--------- nodejs/src/generated/session-events.ts | 48 ++++---- nodejs/src/sessionFsProvider.ts | 22 +++- python/copilot/generated/rpc.py | 1 + rust/src/generated/api_types.rs | 9 +- rust/src/session.rs | 2 + rust/src/session_fs_dispatch.rs | 2 +- rust/tests/e2e/compaction.rs | 4 +- rust/tests/e2e/event_fidelity.rs | 6 +- rust/tests/e2e/mode_handlers.rs | 7 +- rust/tests/e2e/permissions.rs | 10 +- rust/tests/e2e/rpc_additional_edge_cases.rs | 17 ++- rust/tests/e2e/rpc_server.rs | 2 +- rust/tests/e2e/rpc_session_state.rs | 12 +- scripts/codegen/csharp.ts | 35 ++---- scripts/codegen/python.ts | 1 + scripts/codegen/rust.ts | 25 +++- scripts/codegen/typescript.ts | 2 + 35 files changed, 214 insertions(+), 338 deletions(-) diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs index 11eb343a1..b4e197094 100644 --- a/dotnet/src/Generated/Rpc.cs +++ b/dotnet/src/Generated/Rpc.cs @@ -26,7 +26,6 @@ public sealed class PingResult public string Message { get; set; } = string.Empty; /// Server protocol version number. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("protocolVersion")] public long ProtocolVersion { get; set; } @@ -51,7 +50,6 @@ internal sealed class ConnectResult public bool Ok { get; set; } /// Server protocol version number. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("protocolVersion")] public long ProtocolVersion { get; set; } @@ -72,22 +70,18 @@ internal sealed class ConnectRequest public sealed class ModelBillingTokenPrices { /// Number of tokens per standard billing batch. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("batchSize")] public long? BatchSize { get; set; } /// Price per billing batch of cached tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cachePrice")] public long? CachePrice { get; set; } /// Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputPrice")] public long? InputPrice { get; set; } /// Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputPrice")] public long? OutputPrice { get; set; } } @@ -108,12 +102,10 @@ public sealed class ModelBilling public sealed class ModelCapabilitiesLimitsVision { /// Maximum image size in bytes. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_image_size")] public long MaxPromptImageSize { get; set; } /// Maximum number of images per prompt. - [Range((double)1, (double)long.MaxValue)] [JsonPropertyName("max_prompt_images")] public long MaxPromptImages { get; set; } @@ -126,17 +118,14 @@ public sealed class ModelCapabilitiesLimitsVision public sealed class ModelCapabilitiesLimits { /// Maximum total context window size in tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_context_window_tokens")] public long? MaxContextWindowTokens { get; set; } /// Maximum number of output/completion tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_output_tokens")] public long? MaxOutputTokens { get; set; } /// Maximum number of prompt/input tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_tokens")] public long? MaxPromptTokens { get; set; } @@ -281,7 +270,6 @@ internal sealed class ToolsListRequest public sealed class AccountQuotaSnapshot { /// Number of requests included in the entitlement, or -1 for unlimited entitlements. - [Range((double)-1, (double)long.MaxValue)] [JsonPropertyName("entitlementRequests")] public long EntitlementRequests { get; set; } @@ -290,7 +278,6 @@ public sealed class AccountQuotaSnapshot public bool IsUnlimitedEntitlement { get; set; } /// Number of overage requests made this period. - [Range(0, double.MaxValue)] [JsonPropertyName("overage")] public double Overage { get; set; } @@ -311,7 +298,6 @@ public sealed class AccountQuotaSnapshot public bool UsageAllowedWithExhaustedQuota { get; set; } /// Number of requests used so far this period. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("usedRequests")] public long UsedRequests { get; set; } } @@ -596,7 +582,6 @@ public sealed class ConnectedRemoteSessionMetadata public string? Name { get; set; } /// Pull request number associated with the session. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("pullRequestNumber")] public long? PullRequestNumber { get; set; } @@ -751,7 +736,6 @@ internal sealed class SessionsListRequest public SessionsListRequestFilter? Filter { get; set; } /// When provided, only the first N sessions (sorted by modification time, newest first) load full metadata; remaining sessions return basic info only. Use 0 to return only basic info for every session. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("metadataLimit")] public long? MetadataLimit { get; set; } } @@ -923,7 +907,6 @@ public sealed class SessionPruneResult public bool DryRun { get; set; } /// Total bytes freed (actual when not dry-run, projected when dry-run). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("freedBytes")] public long FreedBytes { get; set; } @@ -949,7 +932,6 @@ internal sealed class SessionsPruneOldRequest public bool? IncludeNamed { get; set; } /// Delete sessions whose modifiedTime is at least this many days old. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("olderThanDays")] public long OlderThanDays { get; set; } } @@ -1026,7 +1008,6 @@ internal sealed class SessionsReloadPluginHooksRequest public sealed class SessionLoadDeferredRepoHooksResult { /// Total hook command count (user + plugin + repo) loaded for the session by this call. Captured atomically with startupPrompts so callers don't need to read a separate counter. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("hookCount")] public long HookCount { get; set; } @@ -1130,12 +1111,10 @@ public partial class SendAttachment public sealed class SendAttachmentFileLineRange { /// End line number (1-based, inclusive). - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("end")] public long End { get; set; } /// Start line number (1-based). - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("start")] public long Start { get; set; } } @@ -1183,12 +1162,10 @@ public partial class SendAttachmentDirectory : SendAttachment public sealed class SendAttachmentSelectionDetailsEnd { /// End character offset within the line (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] public long Character { get; set; } /// End line number (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] public long Line { get; set; } } @@ -1197,12 +1174,10 @@ public sealed class SendAttachmentSelectionDetailsEnd public sealed class SendAttachmentSelectionDetailsStart { /// Start character offset within the line (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] public long Character { get; set; } /// Start line number (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] public long Line { get; set; } } @@ -1253,7 +1228,6 @@ public partial class SendAttachmentGithubReference : SendAttachment public override string Type => "github_reference"; /// Issue, pull request, or discussion number. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("number")] public required long Number { get; set; } @@ -2014,12 +1988,10 @@ public sealed class ModelSwitchToResult public sealed class ModelCapabilitiesOverrideLimitsVision { /// Maximum image size in bytes. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_image_size")] public long? MaxPromptImageSize { get; set; } /// Maximum number of images per prompt. - [Range((double)1, (double)long.MaxValue)] [JsonPropertyName("max_prompt_images")] public long? MaxPromptImages { get; set; } @@ -2032,17 +2004,14 @@ public sealed class ModelCapabilitiesOverrideLimitsVision public sealed class ModelCapabilitiesOverrideLimits { /// Maximum total context window size in tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_context_window_tokens")] public long? MaxContextWindowTokens { get; set; } /// Maximum number of output/completion tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_output_tokens")] public long? MaxOutputTokens { get; set; } /// Maximum number of prompt/input tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("max_prompt_tokens")] public long? MaxPromptTokens { get; set; } @@ -2290,7 +2259,6 @@ public sealed class WorkspacesGetWorkspaceResultWorkspace public string? Repository { get; set; } /// Gets or sets the summary_count value. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("summary_count")] public long? SummaryCount { get; set; } @@ -2383,7 +2351,6 @@ public sealed class WorkspacesCheckpoints public string Filename { get; set; } = string.Empty; /// Checkpoint number assigned by the workspace manager. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("number")] public long Number { get; set; } @@ -2420,7 +2387,6 @@ public sealed class WorkspacesReadCheckpointResult internal sealed class WorkspacesReadCheckpointRequest { /// Checkpoint number to read. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("number")] public long Number { get; set; } @@ -2441,7 +2407,6 @@ public sealed class WorkspacesSaveLargePasteResultSaved public string FilePath { get; set; } = string.Empty; /// Size of the saved file in bytes. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("sizeBytes")] public long SizeBytes { get; set; } } @@ -2747,7 +2712,6 @@ public partial class TaskInfoAgent : TaskInfo public DateTimeOffset? ActiveStartedAt { get; set; } /// Accumulated active execution time in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("activeTimeMs")] @@ -2868,7 +2832,6 @@ public partial class TaskInfoShell : TaskInfo public string? LogPath { get; set; } /// Process ID when available. - [Range((double)0, (double)4294967295, MinimumIsExclusive = true)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("pid")] public long? Pid { get; set; } @@ -3152,7 +3115,6 @@ public sealed class SkillsInvokedSkill public string Content { get; set; } = string.Empty; /// Turn number when the skill was invoked. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("invokedAtTurn")] public long InvokedAtTurn { get; set; } @@ -3746,7 +3708,6 @@ public sealed class Extension public string Name { get; set; } = string.Empty; /// Process ID if the extension is running. - [Range((double)0, (double)4294967295, MinimumIsExclusive = true)] [JsonPropertyName("pid")] public long? Pid { get; set; } @@ -5328,7 +5289,6 @@ public sealed class MetadataSnapshotRemoteMetadataRepository public sealed class MetadataSnapshotRemoteMetadata { /// The pull request number the remote session is associated with, if any. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("pullRequestNumber")] public long? PullRequestNumber { get; set; } @@ -5473,22 +5433,18 @@ internal sealed class SessionMetadataIsProcessingRequest public sealed class MetadataContextInfoResultContextInfo { /// Output reserve plus tokens after the buffer-exhaustion blocking threshold (default 95%). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("bufferTokens")] public long BufferTokens { get; set; } /// Token count at which background compaction starts (configurable percentage of promptTokenLimit). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("compactionThreshold")] public long CompactionThreshold { get; set; } /// Tokens consumed by user/assistant/tool messages. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("conversationTokens")] public long ConversationTokens { get; set; } /// Total context limit for /context display. promptTokenLimit + min(32k or 64k, outputTokenLimit) depending on model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("limit")] public long Limit { get; set; } @@ -5497,22 +5453,18 @@ public sealed class MetadataContextInfoResultContextInfo public string ModelName { get; set; } = string.Empty; /// Maximum prompt tokens allowed by the model (or DEFAULT_TOKEN_LIMIT if unspecified). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("promptTokenLimit")] public long PromptTokenLimit { get; set; } /// Tokens consumed by the system prompt. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("systemTokens")] public long SystemTokens { get; set; } /// Tokens consumed by tool definitions sent to the model (excludes deferred tools). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("toolDefinitionsTokens")] public long ToolDefinitionsTokens { get; set; } /// Sum of system, conversation and tool-definition tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalTokens")] public long TotalTokens { get; set; } } @@ -5531,12 +5483,10 @@ public sealed class MetadataContextInfoResult internal sealed class MetadataContextInfoRequest { /// Maximum output tokens allowed by the target model. Pass 0 if unknown. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputTokenLimit")] public long OutputTokenLimit { get; set; } /// Maximum prompt tokens allowed by the target model. Pass 0 to use the runtime default. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("promptTokenLimit")] public long PromptTokenLimit { get; set; } @@ -5632,17 +5582,14 @@ internal sealed class MetadataSetWorkingDirectoryRequest public sealed class MetadataRecomputeContextTokensResult { /// Tokens contributed by user/assistant/tool messages (excludes system/developer prompts). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesTokenCount")] public long MessagesTokenCount { get; set; } /// Tokens contributed by system/developer prompt snapshots. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("systemTokenCount")] public long SystemTokenCount { get; set; } /// Sum of tokens across chat-context and system-context messages currently held by the session. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalTokens")] public long TotalTokens { get; set; } } @@ -5684,7 +5631,6 @@ internal sealed class ShellExecRequest public string SessionId { get; set; } = string.Empty; /// Timeout in milliseconds (default: 30000). - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("timeout")] public TimeSpan? Timeout { get; set; } @@ -5719,32 +5665,26 @@ internal sealed class ShellKillRequest public sealed class HistoryCompactContextWindow { /// Token count from non-system messages (user, assistant, tool). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } /// Current total tokens in the context window (system + conversation + tool definitions). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("currentTokens")] public long CurrentTokens { get; set; } /// Current number of messages in the conversation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesLength")] public long MessagesLength { get; set; } /// Token count from system message(s). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } /// Maximum token count for the model's context window. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] public long TokenLimit { get; set; } /// Token count from tool definitions. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } } @@ -5758,7 +5698,6 @@ public sealed class HistoryCompactResult public HistoryCompactContextWindow? ContextWindow { get; set; } /// Number of messages removed during compaction. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesRemoved")] public long MessagesRemoved { get; set; } @@ -5771,7 +5710,6 @@ public sealed class HistoryCompactResult public string? SummaryContent { get; set; } /// Number of tokens freed by compaction. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokensRemoved")] public long TokensRemoved { get; set; } } @@ -5790,7 +5728,6 @@ internal sealed class SessionHistoryCompactRequest public sealed class HistoryTruncateResult { /// Number of events that were removed. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventsRemoved")] public long EventsRemoved { get; set; } } @@ -5958,7 +5895,6 @@ internal sealed class EventLogReadRequest public string? Cursor { get; set; } /// Maximum number of events to return in this batch (1–1000, default 200). - [Range((double)0, (double)1000, MinimumIsExclusive = true)] [JsonPropertyName("max")] public int? Max { get; set; } @@ -5971,7 +5907,6 @@ internal sealed class EventLogReadRequest public object? Types { get; set; } /// Milliseconds to wait for new events when the cursor is at the tail of history. 0 (default) returns immediately even if no events are available. Capped at 30000ms. Ephemeral events that arrive during the wait are delivered in this batch but are NOT replayable on a subsequent read (use a non-zero waitMs in your next call to capture future ephemerals as they happen). - [Range((double)0, (double)30000)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("waitMs")] public TimeSpan? Wait { get; set; } @@ -6048,17 +5983,14 @@ public sealed class UsageMetricsCodeChanges public IList FilesModified { get => field ??= []; set; } /// Number of distinct files modified. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("filesModifiedCount")] public long FilesModifiedCount { get; set; } /// Total lines of code added. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesAdded")] public long LinesAdded { get; set; } /// Total lines of code removed. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesRemoved")] public long LinesRemoved { get; set; } } @@ -6072,7 +6004,6 @@ public sealed class UsageMetricsModelMetricRequests public double Cost { get; set; } /// Number of API requests made with this model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("count")] public long Count { get; set; } } @@ -6082,7 +6013,6 @@ public sealed class UsageMetricsModelMetricRequests public sealed class UsageMetricsModelMetricTokenDetail { /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public long TokenCount { get; set; } } @@ -6092,27 +6022,22 @@ public sealed class UsageMetricsModelMetricTokenDetail public sealed class UsageMetricsModelMetricUsage { /// Total tokens read from prompt cache. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheReadTokens")] public long CacheReadTokens { get; set; } /// Total tokens written to prompt cache. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheWriteTokens")] public long CacheWriteTokens { get; set; } /// Total input tokens consumed. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputTokens")] public long InputTokens { get; set; } /// Total output tokens produced. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputTokens")] public long OutputTokens { get; set; } /// Total output tokens used for reasoning. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("reasoningTokens")] public long? ReasoningTokens { get; set; } } @@ -6130,7 +6055,6 @@ public sealed class UsageMetricsModelMetric public IDictionary? TokenDetails { get; set; } /// Accumulated nano-AI units cost for this model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] public long? TotalNanoAiu { get; set; } @@ -6144,7 +6068,6 @@ public sealed class UsageMetricsModelMetric public sealed class UsageMetricsTokenDetail { /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public long TokenCount { get; set; } } @@ -6162,12 +6085,10 @@ public sealed class UsageGetMetricsResult public string? CurrentModel { get; set; } /// Input tokens from the most recent main-agent API call. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("lastCallInputTokens")] public long LastCallInputTokens { get; set; } /// Output tokens from the most recent main-agent API call. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("lastCallOutputTokens")] public long LastCallOutputTokens { get; set; } @@ -6184,13 +6105,11 @@ public sealed class UsageGetMetricsResult public IDictionary? TokenDetails { get; set; } /// Total time spent in model API calls (milliseconds). - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("totalApiDurationMs")] public TimeSpan TotalApiDuration { get; set; } /// Session-wide accumulated nano-AI units cost. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] public long? TotalNanoAiu { get; set; } @@ -6199,7 +6118,6 @@ public sealed class UsageGetMetricsResult public double TotalPremiumRequestCost { get; set; } /// Raw count of user-initiated API requests. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalUserRequests")] public long TotalUserRequests { get; set; } } @@ -6278,12 +6196,10 @@ public sealed class ScheduleEntry public string? DisplayPrompt { get; set; } /// Sequential id assigned by the runtime within the session. Stable across resumes (rebuilt from the event log). - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("id")] public long Id { get; set; } /// Interval between scheduled ticks, in milliseconds. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("intervalMs")] public TimeSpan Interval { get; set; } @@ -6333,7 +6249,6 @@ public sealed class ScheduleStopResult internal sealed class ScheduleStopRequest { /// Id of the scheduled prompt to remove. - [Range((double)0, (double)long.MaxValue, MinimumIsExclusive = true)] [JsonPropertyName("id")] public long Id { get; set; } @@ -6386,7 +6301,6 @@ public sealed class SessionFsWriteFileRequest public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } @@ -6407,7 +6321,6 @@ public sealed class SessionFsAppendFileRequest public string Content { get; set; } = string.Empty; /// Optional POSIX-style mode for newly created files. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } @@ -6464,7 +6377,6 @@ public sealed class SessionFsStatResult public DateTimeOffset Mtime { get; set; } /// File size in bytes. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("size")] public long Size { get; set; } } @@ -6485,7 +6397,6 @@ public sealed class SessionFsStatRequest public sealed class SessionFsMkdirRequest { /// Optional POSIX-style mode for newly created directories. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("mode")] public long? Mode { get; set; } @@ -6618,7 +6529,6 @@ public sealed class SessionFsSqliteQueryResult public IList> Rows { get => field ??= []; set; } /// Number of rows affected (for INSERT/UPDATE/DELETE). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("rowsAffected")] public long RowsAffected { get; set; } } diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 24f130b44..534bd3bba 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -1278,7 +1278,6 @@ public sealed partial class SessionResumeData public bool? ContinuePendingWork { get; set; } /// Total number of persisted events in the session at the time of resume. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventCount")] public required long EventCount { get; set; } @@ -1352,7 +1351,6 @@ public sealed partial class SessionErrorData public string? Stack { get; set; } /// HTTP status code from the upstream request, if applicable. - [Range((double)100, (double)599)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("statusCode")] public int? StatusCode { get; set; } @@ -1573,7 +1571,6 @@ public sealed partial class SessionHandoffData public sealed partial class SessionTruncationData { /// Number of messages removed by truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesRemovedDuringTruncation")] public required long MessagesRemovedDuringTruncation { get; set; } @@ -1582,32 +1579,26 @@ public sealed partial class SessionTruncationData public required string PerformedBy { get; set; } /// Number of conversation messages after truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("postTruncationMessagesLength")] public required long PostTruncationMessagesLength { get; set; } /// Total tokens in conversation messages after truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("postTruncationTokensInMessages")] public required long PostTruncationTokensInMessages { get; set; } /// Number of conversation messages before truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("preTruncationMessagesLength")] public required long PreTruncationMessagesLength { get; set; } /// Total tokens in conversation messages before truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("preTruncationTokensInMessages")] public required long PreTruncationTokensInMessages { get; set; } /// Maximum token count for the model's context window. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] public required long TokenLimit { get; set; } /// Number of tokens removed by truncation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokensRemovedDuringTruncation")] public required long TokensRemovedDuringTruncation { get; set; } } @@ -1616,7 +1607,6 @@ public sealed partial class SessionTruncationData public sealed partial class SessionSnapshotRewindData { /// Number of events that were removed by the rewind. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("eventsRemoved")] public required long EventsRemoved { get; set; } @@ -1633,7 +1623,6 @@ public sealed partial class SessionShutdownData public required ShutdownCodeChanges CodeChanges { get; set; } /// Non-system message token count at shutdown. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } @@ -1644,7 +1633,6 @@ public sealed partial class SessionShutdownData public string? CurrentModel { get; set; } /// Total tokens in context window at shutdown. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("currentTokens")] public long? CurrentTokens { get; set; } @@ -1659,7 +1647,6 @@ public sealed partial class SessionShutdownData public required IDictionary ModelMetrics { get; set; } /// Unix timestamp (milliseconds) when the session started. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("sessionStartTime")] public required long SessionStartTime { get; set; } @@ -1668,7 +1655,6 @@ public sealed partial class SessionShutdownData public required ShutdownType ShutdownType { get; set; } /// System message token count at shutdown. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } @@ -1679,25 +1665,21 @@ public sealed partial class SessionShutdownData public IDictionary? TokenDetails { get; set; } /// Tool definitions token count at shutdown. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } /// Cumulative time spent in API calls during the session, in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonPropertyName("totalApiDurationMs")] public required TimeSpan TotalApiDuration { get; set; } /// Session-wide accumulated nano-AI units cost. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalNanoAiu")] public long? TotalNanoAiu { get; set; } /// Total number of premium API requests used during the session. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalPremiumRequests")] public required long TotalPremiumRequests { get; set; } } @@ -1749,13 +1731,11 @@ public sealed partial class SessionContextChangedData public sealed partial class SessionUsageInfoData { /// Token count from non-system messages (user, assistant, tool). - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } /// Current number of tokens in the context window. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("currentTokens")] public required long CurrentTokens { get; set; } @@ -1765,23 +1745,19 @@ public sealed partial class SessionUsageInfoData public bool? IsInitial { get; set; } /// Current number of messages in the conversation. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("messagesLength")] public required long MessagesLength { get; set; } /// Token count from system message(s). - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } /// Maximum token count for the model's context window. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenLimit")] public required long TokenLimit { get; set; } /// Token count from tool definitions. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } @@ -1791,19 +1767,16 @@ public sealed partial class SessionUsageInfoData public sealed partial class SessionCompactionStartData { /// Token count from non-system messages (user, assistant, tool) at compaction start. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } /// Token count from system message(s) at compaction start. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } /// Token count from tool definitions at compaction start. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } @@ -1813,7 +1786,6 @@ public sealed partial class SessionCompactionStartData public sealed partial class SessionCompactionCompleteData { /// Checkpoint snapshot number created for recovery. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("checkpointNumber")] public long? CheckpointNumber { get; set; } @@ -1829,7 +1801,6 @@ public sealed partial class SessionCompactionCompleteData public CompactionCompleteCompactionTokensUsed? CompactionTokensUsed { get; set; } /// Token count from non-system messages (user, assistant, tool) after compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("conversationTokens")] public long? ConversationTokens { get; set; } @@ -1840,25 +1811,21 @@ public sealed partial class SessionCompactionCompleteData public string? Error { get; set; } /// Number of messages removed during compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("messagesRemoved")] public long? MessagesRemoved { get; set; } /// Total tokens in conversation after compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("postCompactionTokens")] public long? PostCompactionTokens { get; set; } /// Number of messages before compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("preCompactionMessagesLength")] public long? PreCompactionMessagesLength { get; set; } /// Total tokens in conversation before compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("preCompactionTokens")] public long? PreCompactionTokens { get; set; } @@ -1878,19 +1845,16 @@ public sealed partial class SessionCompactionCompleteData public string? SummaryContent { get; set; } /// Token count from system message(s) after compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("systemTokens")] public long? SystemTokens { get; set; } /// Number of tokens removed during compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("tokensRemoved")] public long? TokensRemoved { get; set; } /// Token count from tool definitions after compaction. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("toolDefinitionsTokens")] public long? ToolDefinitionsTokens { get; set; } @@ -2017,7 +1981,6 @@ public sealed partial class AssistantReasoningDeltaData public sealed partial class AssistantStreamingDeltaData { /// Cumulative total bytes received from the streaming response so far. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalResponseSizeBytes")] public required long TotalResponseSizeBytes { get; set; } } @@ -2059,7 +2022,6 @@ public sealed partial class AssistantMessageData public string? Model { get; set; } /// Actual output token count from the API response (completion_tokens), used for accurate token accounting. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] public long? OutputTokens { get; set; } @@ -2156,13 +2118,11 @@ public sealed partial class AssistantUsageData public AssistantUsageApiEndpoint? ApiEndpoint { get; set; } /// Number of tokens read from prompt cache. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheReadTokens")] public long? CacheReadTokens { get; set; } /// Number of tokens written to prompt cache. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheWriteTokens")] public long? CacheWriteTokens { get; set; } @@ -2178,7 +2138,6 @@ public sealed partial class AssistantUsageData public double? Cost { get; set; } /// Duration of the API call in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("duration")] @@ -2190,13 +2149,11 @@ public sealed partial class AssistantUsageData public string? Initiator { get; set; } /// Number of input tokens consumed. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("inputTokens")] public long? InputTokens { get; set; } /// Average inter-token latency in milliseconds. Only available for streaming requests. - [Range(0, double.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("interTokenLatencyMs")] @@ -2207,7 +2164,6 @@ public sealed partial class AssistantUsageData public required string Model { get; set; } /// Number of output tokens produced. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] public long? OutputTokens { get; set; } @@ -2235,13 +2191,11 @@ public sealed partial class AssistantUsageData public string? ReasoningEffort { get; set; } /// Number of output tokens used for reasoning (e.g., chain-of-thought). - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("reasoningTokens")] public long? ReasoningTokens { get; set; } /// Time to first token in milliseconds. Only available for streaming requests. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("ttftMs")] @@ -2257,7 +2211,6 @@ public sealed partial class ModelCallFailureData public string? ApiCallId { get; set; } /// Duration of the failed API call in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2288,7 +2241,6 @@ public sealed partial class ModelCallFailureData public required ModelCallFailureSource Source { get; set; } /// HTTP status code from the failed request. - [Range((double)100, (double)599)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("statusCode")] public int? StatusCode { get; set; } @@ -2509,7 +2461,6 @@ public sealed partial class SubagentCompletedData public required string AgentName { get; set; } /// Wall-clock duration of the sub-agent execution in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2525,13 +2476,11 @@ public sealed partial class SubagentCompletedData public required string ToolCallId { get; set; } /// Total tokens (input + output) consumed by the sub-agent. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalTokens")] public long? TotalTokens { get; set; } /// Total number of tool calls made by the sub-agent. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalToolCalls")] public long? TotalToolCalls { get; set; } @@ -2549,7 +2498,6 @@ public sealed partial class SubagentFailedData public required string AgentName { get; set; } /// Wall-clock duration of the sub-agent execution in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("durationMs")] @@ -2569,13 +2517,11 @@ public sealed partial class SubagentFailedData public required string ToolCallId { get; set; } /// Total tokens (input + output) consumed before the sub-agent failed. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalTokens")] public long? TotalTokens { get; set; } /// Total number of tool calls made before the sub-agent failed. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalToolCalls")] public long? TotalToolCalls { get; set; } @@ -2999,7 +2945,6 @@ public sealed partial class AutoModeSwitchRequestedData public required string RequestId { get; set; } /// Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("retryAfterSeconds")] @@ -3223,12 +3168,10 @@ public sealed partial class ShutdownCodeChanges public required string[] FilesModified { get; set; } /// Total number of lines added during the session. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesAdded")] public required long LinesAdded { get; set; } /// Total number of lines removed during the session. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("linesRemoved")] public required long LinesRemoved { get; set; } } @@ -3242,7 +3185,6 @@ public sealed partial class ShutdownModelMetricRequests public required double Cost { get; set; } /// Total number of API requests made to this model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("count")] public required long Count { get; set; } } @@ -3252,7 +3194,6 @@ public sealed partial class ShutdownModelMetricRequests public sealed partial class ShutdownModelMetricTokenDetail { /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public required long TokenCount { get; set; } } @@ -3262,27 +3203,22 @@ public sealed partial class ShutdownModelMetricTokenDetail public sealed partial class ShutdownModelMetricUsage { /// Total tokens read from prompt cache across all requests. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheReadTokens")] public required long CacheReadTokens { get; set; } /// Total tokens written to prompt cache across all requests. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("cacheWriteTokens")] public required long CacheWriteTokens { get; set; } /// Total input tokens consumed across all requests to this model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("inputTokens")] public required long InputTokens { get; set; } /// Total output tokens produced across all requests to this model. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("outputTokens")] public required long OutputTokens { get; set; } /// Total reasoning tokens produced across all requests to this model. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("reasoningTokens")] public long? ReasoningTokens { get; set; } @@ -3302,7 +3238,6 @@ public sealed partial class ShutdownModelMetric public IDictionary? TokenDetails { get; set; } /// Accumulated nano-AI units cost for this model. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("totalNanoAiu")] public long? TotalNanoAiu { get; set; } @@ -3317,7 +3252,6 @@ public sealed partial class ShutdownModelMetric public sealed partial class ShutdownTokenDetail { /// Accumulated token count for this token type. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public required long TokenCount { get; set; } } @@ -3331,12 +3265,10 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsageTo public required long BatchSize { get; set; } /// Cost per batch of tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("costPerBatch")] public required long CostPerBatch { get; set; } /// Total token count for this entry. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public required long TokenCount { get; set; } @@ -3354,7 +3286,6 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsage public required CompactionCompleteCompactionTokensUsedCopilotUsageTokenDetail[] TokenDetails { get; set; } /// Total cost in nano-AI units for this request. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] public required long TotalNanoAiu { get; set; } } @@ -3364,13 +3295,11 @@ public sealed partial class CompactionCompleteCompactionTokensUsedCopilotUsage public sealed partial class CompactionCompleteCompactionTokensUsed { /// Cached input tokens reused in the compaction LLM call. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheReadTokens")] public long? CacheReadTokens { get; set; } /// Tokens written to prompt cache in the compaction LLM call. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("cacheWriteTokens")] public long? CacheWriteTokens { get; set; } @@ -3381,14 +3310,12 @@ public sealed partial class CompactionCompleteCompactionTokensUsed public CompactionCompleteCompactionTokensUsedCopilotUsage? CopilotUsage { get; set; } /// Duration of the compaction LLM call in milliseconds. - [Range((double)0, (double)long.MaxValue)] [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("duration")] public TimeSpan? Duration { get; set; } /// Input tokens consumed by the compaction LLM call. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("inputTokens")] public long? InputTokens { get; set; } @@ -3399,7 +3326,6 @@ public sealed partial class CompactionCompleteCompactionTokensUsed public string? Model { get; set; } /// Output tokens produced by the compaction LLM call. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("outputTokens")] public long? OutputTokens { get; set; } @@ -3462,12 +3388,10 @@ public sealed partial class UserMessageAttachmentDirectory : UserMessageAttachme public sealed partial class UserMessageAttachmentSelectionDetailsEnd { /// End character offset within the line (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] public required long Character { get; set; } /// End line number (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] public required long Line { get; set; } } @@ -3477,12 +3401,10 @@ public sealed partial class UserMessageAttachmentSelectionDetailsEnd public sealed partial class UserMessageAttachmentSelectionDetailsStart { /// Start character offset within the line (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("character")] public required long Character { get; set; } /// Start line number (0-based). - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("line")] public required long Line { get; set; } } @@ -3649,12 +3571,10 @@ public sealed partial class AssistantUsageCopilotUsageTokenDetail public required long BatchSize { get; set; } /// Cost per batch of tokens. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("costPerBatch")] public required long CostPerBatch { get; set; } /// Total token count for this entry. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("tokenCount")] public required long TokenCount { get; set; } @@ -3672,7 +3592,6 @@ public sealed partial class AssistantUsageCopilotUsage public required AssistantUsageCopilotUsageTokenDetail[] TokenDetails { get; set; } /// Total cost in nano-AI units for this request. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("totalNanoAiu")] public required long TotalNanoAiu { get; set; } } @@ -3682,7 +3601,6 @@ public sealed partial class AssistantUsageCopilotUsage public sealed partial class AssistantUsageQuotaSnapshot { /// Total requests allowed by the entitlement. - [Range((double)-1, (double)long.MaxValue)] [JsonPropertyName("entitlementRequests")] public required long EntitlementRequests { get; set; } @@ -3691,7 +3609,6 @@ public sealed partial class AssistantUsageQuotaSnapshot public required bool IsUnlimitedEntitlement { get; set; } /// Number of requests over the entitlement limit. - [Range(0, double.MaxValue)] [JsonPropertyName("overage")] public required double Overage { get; set; } @@ -3700,7 +3617,6 @@ public sealed partial class AssistantUsageQuotaSnapshot public required bool OverageAllowedWithExhaustedQuota { get; set; } /// Percentage of quota remaining (0 to 100). - [Range(0, 100)] [JsonPropertyName("remainingPercentage")] public required double RemainingPercentage { get; set; } @@ -3714,7 +3630,6 @@ public sealed partial class AssistantUsageQuotaSnapshot public required bool UsageAllowedWithExhaustedQuota { get; set; } /// Number of requests already consumed. - [Range((double)0, (double)long.MaxValue)] [JsonPropertyName("usedRequests")] public required long UsedRequests { get; set; } } @@ -3760,7 +3675,6 @@ public sealed partial class ToolExecutionCompleteContentTerminal : ToolExecution public string? Cwd { get; set; } /// Process exit code, if the command has completed. - [Range((double)0, (double)4294967295)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("exitCode")] public long? ExitCode { get; set; } @@ -3858,7 +3772,6 @@ public sealed partial class ToolExecutionCompleteContentResourceLink : ToolExecu public required string Name { get; set; } /// Size of the resource in bytes. - [Range((double)0, (double)long.MaxValue)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("size")] public long? Size { get; set; } @@ -4160,7 +4073,6 @@ public sealed partial class SystemNotificationShellCompleted : SystemNotificatio public string? Description { get; set; } /// Exit code of the shell command, if available. - [Range((double)0, (double)4294967295)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("exitCode")] public long? ExitCode { get; set; } diff --git a/dotnet/src/Session.cs b/dotnet/src/Session.cs index d014a33a0..1ca9eb621 100644 --- a/dotnet/src/Session.cs +++ b/dotnet/src/Session.cs @@ -1427,7 +1427,7 @@ public async Task LogAsync(string message, SessionLogLevel? level = null, bool? ArgumentNullException.ThrowIfNull(message); ThrowIfDisposed(); - await Rpc.LogAsync(message, level, ephemeral, url, cancellationToken); + await Rpc.LogAsync(message, level, ephemeral: ephemeral, url: url, cancellationToken: cancellationToken); } /// diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index d39bfe02d..78b65c0ca 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -103,9 +103,10 @@ public async Task Should_Invoke_Auto_Mode_Switch_Handler_When_Rate_Limited() }, }); + var expectedRetryAfter = TimeSpan.FromMilliseconds(1); var requestedEventTask = GetNextEventOfTypeAllowingRateLimitAsync( session, - evt => evt.Data.ErrorCode == "user_weekly_rate_limited" && evt.Data.RetryAfterSeconds == 1, + evt => evt.Data.ErrorCode == "user_weekly_rate_limited" && evt.Data.RetryAfterSeconds == expectedRetryAfter, TimeSpan.FromSeconds(30), timeoutDescription: "auto_mode_switch.requested event"); var completedEventTask = GetNextEventOfTypeAllowingRateLimitAsync( @@ -137,7 +138,7 @@ public async Task Should_Invoke_Auto_Mode_Switch_Handler_When_Rate_Limited() var requestedEvent = await requestedEventTask; Assert.Equal(request.ErrorCode, requestedEvent.Data.ErrorCode); - Assert.Equal(request.RetryAfterSeconds, requestedEvent.Data.RetryAfterSeconds); + Assert.Equal(expectedRetryAfter, requestedEvent.Data.RetryAfterSeconds); var completedEvent = await completedEventTask; Assert.Equal(AutoModeSwitchResponse.Yes, completedEvent.Data.Response); diff --git a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs index 463fdc96a..092012399 100644 --- a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs +++ b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs @@ -155,7 +155,7 @@ public async Task Usage_GetMetrics_On_Fresh_Session_Returns_Zero_Tokens() Assert.Equal(0, metrics.LastCallInputTokens); Assert.Equal(0, metrics.LastCallOutputTokens); Assert.Equal(0, metrics.TotalUserRequests); - Assert.True(metrics.SessionStartTime > 0, "SessionStartTime should be a positive epoch."); + Assert.NotEqual(default, metrics.SessionStartTime); } [Fact] diff --git a/dotnet/test/E2E/RpcServerE2ETests.cs b/dotnet/test/E2E/RpcServerE2ETests.cs index 847a28c3b..b7d7e4624 100644 --- a/dotnet/test/E2E/RpcServerE2ETests.cs +++ b/dotnet/test/E2E/RpcServerE2ETests.cs @@ -45,7 +45,7 @@ public async Task Should_Call_Rpc_Ping_With_Typed_Params_And_Result() var result = await Client.Rpc.PingAsync(message: "typed rpc test"); Assert.Equal("pong: typed rpc test", result.Message); - Assert.True(result.Timestamp >= 0); + Assert.NotEqual(default, result.Timestamp); } [Fact] diff --git a/dotnet/test/E2E/RpcSessionStateE2ETests.cs b/dotnet/test/E2E/RpcSessionStateE2ETests.cs index 9b0b4df3b..d92307efd 100644 --- a/dotnet/test/E2E/RpcSessionStateE2ETests.cs +++ b/dotnet/test/E2E/RpcSessionStateE2ETests.cs @@ -356,7 +356,7 @@ public async Task Should_Call_Session_Usage_And_Permission_Rpcs() await using var session = await CreateSessionAsync(); var metrics = await session.Rpc.Usage.GetMetricsAsync(); - Assert.True(metrics.SessionStartTime > 0); + Assert.NotEqual(default, metrics.SessionStartTime); Assert.True(metrics.TotalNanoAiu is null or >= 0); if (metrics.TokenDetails is not null) { diff --git a/go/client.go b/go/client.go index dcf793d5a..9fa772129 100644 --- a/go/client.go +++ b/go/client.go @@ -1312,7 +1312,7 @@ func (c *Client) ActualPort() int { // if err != nil { // log.Printf("Server unreachable: %v", err) // } else { -// log.Printf("Server responded at %d", resp.Timestamp) +// log.Printf("Server responded at %s", resp.Timestamp) // } func (c *Client) Ping(ctx context.Context, message string) (*PingResponse, error) { if c.client == nil { diff --git a/go/internal/e2e/client_e2e_test.go b/go/internal/e2e/client_e2e_test.go index b23df44f1..9fda3cd83 100644 --- a/go/internal/e2e/client_e2e_test.go +++ b/go/internal/e2e/client_e2e_test.go @@ -38,8 +38,8 @@ func TestClientE2E(t *testing.T) { t.Errorf("Expected pong.message to be 'pong: test message', got %q", pong.Message) } - if pong.Timestamp < 0 { - t.Errorf("Expected pong.timestamp >= 0, got %d", pong.Timestamp) + if pong.Timestamp.IsZero() { + t.Errorf("Expected non-zero pong.timestamp, got %s", pong.Timestamp) } if err := client.Stop(); err != nil { @@ -75,8 +75,8 @@ func TestClientE2E(t *testing.T) { t.Errorf("Expected pong.message to be 'pong: test message', got %q", pong.Message) } - if pong.Timestamp < 0 { - t.Errorf("Expected pong.timestamp >= 0, got %d", pong.Timestamp) + if pong.Timestamp.IsZero() { + t.Errorf("Expected non-zero pong.timestamp, got %s", pong.Timestamp) } if err := client.Stop(); err != nil { diff --git a/go/internal/e2e/rpc_e2e_test.go b/go/internal/e2e/rpc_e2e_test.go index ead3d54d3..8f73afa9e 100644 --- a/go/internal/e2e/rpc_e2e_test.go +++ b/go/internal/e2e/rpc_e2e_test.go @@ -35,8 +35,8 @@ func TestRpcE2E(t *testing.T) { t.Errorf("Expected message 'pong: typed rpc test', got %q", result.Message) } - if result.Timestamp < 0 { - t.Errorf("Expected timestamp >= 0, got %d", result.Timestamp) + if result.Timestamp.IsZero() { + t.Errorf("Expected non-zero timestamp, got %s", result.Timestamp) } if err := client.Stop(); err != nil { diff --git a/go/internal/e2e/rpc_event_side_effects_e2e_test.go b/go/internal/e2e/rpc_event_side_effects_e2e_test.go index 1c63a3aea..55f9835f3 100644 --- a/go/internal/e2e/rpc_event_side_effects_e2e_test.go +++ b/go/internal/e2e/rpc_event_side_effects_e2e_test.go @@ -199,7 +199,7 @@ func TestRpcEventSideEffectsE2E(t *testing.T) { if !strings.EqualFold(rewindData.UpToEventID, targetEventID) { t.Fatalf("Expected rewind to target %q, got %+v", targetEventID, rewindData) } - if rewindData.EventsRemoved != float64(truncateResult.EventsRemoved) { + if rewindData.EventsRemoved != truncateResult.EventsRemoved { t.Fatalf("Expected rewind count %d, got %+v", truncateResult.EventsRemoved, rewindData) } diff --git a/go/internal/e2e/rpc_server_e2e_test.go b/go/internal/e2e/rpc_server_e2e_test.go index e674a4371..aaf9eafbc 100644 --- a/go/internal/e2e/rpc_server_e2e_test.go +++ b/go/internal/e2e/rpc_server_e2e_test.go @@ -33,8 +33,8 @@ func TestRpcServerE2E(t *testing.T) { if !strings.Contains(result.Message, "typed rpc test") { t.Errorf("Expected ping response to contain 'typed rpc test', got %q", result.Message) } - if result.Timestamp < 0 { - t.Errorf("Expected non-negative Timestamp, got %d", result.Timestamp) + if result.Timestamp.IsZero() { + t.Errorf("Expected non-zero Timestamp, got %s", result.Timestamp) } }) diff --git a/go/internal/e2e/rpc_session_state_e2e_test.go b/go/internal/e2e/rpc_session_state_e2e_test.go index 116f48760..b46095d70 100644 --- a/go/internal/e2e/rpc_session_state_e2e_test.go +++ b/go/internal/e2e/rpc_session_state_e2e_test.go @@ -469,8 +469,8 @@ func TestRpcSessionStateE2E(t *testing.T) { if err != nil { t.Fatalf("Failed to get usage metrics: %v", err) } - if metrics.SessionStartTime <= 0 { - t.Errorf("Expected positive sessionStartTime, got %d", metrics.SessionStartTime) + if metrics.SessionStartTime.IsZero() { + t.Errorf("Expected non-zero sessionStartTime, got %s", metrics.SessionStartTime) } if metrics.TotalNanoAiu != nil && *metrics.TotalNanoAiu < 0 { t.Errorf("Expected non-negative totalNanoAiu, got %d", *metrics.TotalNanoAiu) diff --git a/go/internal/e2e/session_e2e_test.go b/go/internal/e2e/session_e2e_test.go index 4b0b74c31..f0d249422 100644 --- a/go/internal/e2e/session_e2e_test.go +++ b/go/internal/e2e/session_e2e_test.go @@ -1457,7 +1457,7 @@ func TestSessionAttachmentsE2E(t *testing.T) { t.Fatalf("CreateSession failed: %v", err) } - number := float64(1234) + number := int64(1234) referenceType := copilot.UserMessageAttachmentGithubReferenceTypeIssue state := "open" title := "Add E2E attachment coverage" diff --git a/go/session.go b/go/session.go index 8ee005709..bc7e2ede9 100644 --- a/go/session.go +++ b/go/session.go @@ -847,11 +847,11 @@ func (ui *SessionUI) Input(ctx context.Context, message string, opts *InputOptio prop.Description = &opts.Description } if opts.MinLength != nil { - f := float64(*opts.MinLength) + f := int64(*opts.MinLength) prop.MinLength = &f } if opts.MaxLength != nil { - f := float64(*opts.MaxLength) + f := int64(*opts.MaxLength) prop.MaxLength = &f } if opts.Format != "" { diff --git a/go/session_fs_provider.go b/go/session_fs_provider.go index 3a6f297f8..f77a5317c 100644 --- a/go/session_fs_provider.go +++ b/go/session_fs_provider.go @@ -217,10 +217,10 @@ func (a *sessionFsAdapter) SqliteQuery(request *rpc.SessionFsSqliteQueryRequest) RowsAffected: 0, }, nil } - var wireRowid *float64 + var wireRowid *int64 if result.LastInsertRowid != nil { - f := float64(*result.LastInsertRowid) - wireRowid = &f + rowid := *result.LastInsertRowid + wireRowid = &rowid } return &rpc.SessionFsSqliteQueryResult{ Columns: result.Columns, diff --git a/go/types.go b/go/types.go index f568d1325..19bc892cc 100644 --- a/go/types.go +++ b/go/types.go @@ -3,6 +3,7 @@ package copilot import ( "context" "encoding/json" + "time" "github.com/github/copilot-sdk/go/rpc" ) @@ -1316,9 +1317,9 @@ type pingRequest struct { // PingResponse is the response from a ping request type PingResponse struct { - Message string `json:"message"` - Timestamp int64 `json:"timestamp"` - ProtocolVersion *int `json:"protocolVersion,omitempty"` + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + ProtocolVersion *int `json:"protocolVersion,omitempty"` } // getStatusRequest is the request for status.get diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts index 1e42ef3e7..20a4d6afe 100644 --- a/nodejs/src/generated/rpc.ts +++ b/nodejs/src/generated/rpc.ts @@ -696,13 +696,16 @@ export type UIElicitationFieldValue = string | number | boolean | string[]; * via the `definition` "UIElicitationSchemaProperty". */ export type UIElicitationSchemaProperty = - | UIElicitationStringEnumField - | UIElicitationStringOneOfField - | UIElicitationArrayEnumField - | UIElicitationArrayAnyOfField - | UIElicitationSchemaPropertyBoolean - | UIElicitationSchemaPropertyString - | UIElicitationSchemaPropertyNumber; + | ( + | UIElicitationStringEnumField + | UIElicitationStringOneOfField + | UIElicitationArrayEnumField + | UIElicitationArrayAnyOfField + | UIElicitationSchemaPropertyBoolean + | UIElicitationSchemaPropertyString + | UIElicitationSchemaPropertyNumber + ) + | undefined; /** * Optional format hint that constrains the accepted input. * @@ -775,7 +778,7 @@ export interface AccountGetQuotaResult { * Quota snapshots keyed by type (e.g., chat, completions, premium_interactions) */ quotaSnapshots: { - [k: string]: AccountQuotaSnapshot; + [k: string]: AccountQuotaSnapshot | undefined; }; } /** @@ -876,7 +879,7 @@ export interface AgentInfo { * MCP server configurations attached to this agent, keyed by server name. Server config shape mirrors the MCP `mcpServers` schema. */ mcpServers?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Skill names preloaded into this agent's context. Omitted means none. @@ -966,7 +969,7 @@ export interface CopilotUserResponse { assigned_date?: | ( | { - [k: string]: unknown; + [k: string]: unknown | undefined; } | string ) @@ -980,13 +983,13 @@ export interface CopilotUserResponse { organization_list?: | ( | { - [k: string]: unknown; + [k: string]: unknown | undefined; } | ({ login?: | ( | { - [k: string]: unknown; + [k: string]: unknown | undefined; } | string ) @@ -994,7 +997,7 @@ export interface CopilotUserResponse { name?: | ( | { - [k: string]: unknown; + [k: string]: unknown | undefined; } | string ) @@ -1006,7 +1009,7 @@ export interface CopilotUserResponse { is_mcp_enabled?: | ( | { - [k: string]: unknown; + [k: string]: unknown | undefined; } | boolean ) @@ -1017,11 +1020,11 @@ export interface CopilotUserResponse { token_based_billing?: boolean; quota_reset_date_utc?: string; limited_user_quotas?: { - [k: string]: number; + [k: string]: number | undefined; }; limited_user_reset_date?: string; monthly_quotas?: { - [k: string]: number; + [k: string]: number | undefined; }; cloud_session_storage_enabled?: boolean; cli_remote_control_enabled?: boolean; @@ -1048,20 +1051,22 @@ export interface CopilotUserResponseQuotaSnapshots { chat?: CopilotUserResponseQuotaSnapshotsChat; completions?: CopilotUserResponseQuotaSnapshotsCompletions; premium_interactions?: CopilotUserResponseQuotaSnapshotsPremiumInteractions; - [k: string]: { - entitlement?: number; - overage_count?: number; - overage_permitted?: boolean; - percent_remaining?: number; - quota_id?: string; - quota_remaining?: number; - remaining?: number; - unlimited?: boolean; - timestamp_utc?: string; - has_quota?: boolean; - quota_reset_at?: number; - token_based_billing?: boolean; - } | null; + [k: string]: + | ({ + entitlement?: number; + overage_count?: number; + overage_permitted?: boolean; + percent_remaining?: number; + quota_id?: string; + quota_remaining?: number; + remaining?: number; + unlimited?: boolean; + timestamp_utc?: string; + has_quota?: boolean; + quota_reset_at?: number; + token_based_billing?: boolean; + } | null) + | undefined; } /** * Schema for the `CopilotUserResponseQuotaSnapshotsChat` type. @@ -1798,7 +1803,7 @@ export interface ExternalToolTextResultForLlm { * Optional tool-specific telemetry */ toolTelemetry?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Base64-encoded binary results returned to the model @@ -1808,7 +1813,7 @@ export interface ExternalToolTextResultForLlm { * Structured content blocks from the tool */ contents?: ExternalToolTextResultForLlmContent[]; - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Binary result returned by a tool for the model @@ -2431,7 +2436,7 @@ export interface McpServerConfigStdio { * Environment variables to pass to the Stdio MCP server process. */ env?: { - [k: string]: string; + [k: string]: string | undefined; }; } /** @@ -2463,7 +2468,7 @@ export interface McpServerConfigHttp { * HTTP headers to include in requests to the remote MCP server. */ headers?: { - [k: string]: string; + [k: string]: string | undefined; }; /** * OAuth client ID for a pre-registered remote MCP OAuth client. @@ -2631,7 +2636,7 @@ export interface McpExecuteSamplingParams { */ /** @experimental */ export interface McpExecuteSamplingRequest { - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * MCP CreateMessageResult payload (with optional 'tools' extension), present when action='success'. Treated as opaque at the schema layer; consumers should construct/consume it per the MCP CreateMessageResult shape. @@ -2641,7 +2646,7 @@ export interface McpExecuteSamplingRequest { */ /** @experimental */ export interface McpExecuteSamplingResult { - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Remote MCP server name and optional overrides controlling reauthentication, OAuth client display name, and the callback success-page copy. @@ -4015,7 +4020,7 @@ export interface PermissionsConfigureAdditionalContentExclusionPolicy { rules: PermissionsConfigureAdditionalContentExclusionPolicyRule[]; last_updated_at: string | number; scope: PermissionsConfigureAdditionalContentExclusionPolicyScope; - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRule` type. @@ -4028,7 +4033,7 @@ export interface PermissionsConfigureAdditionalContentExclusionPolicyRule { ifAnyMatch?: string[]; ifNoneMatch?: string[]; source: PermissionsConfigureAdditionalContentExclusionPolicyRuleSource; - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Schema for the `PermissionsConfigureAdditionalContentExclusionPolicyRuleSource` type. @@ -4795,14 +4800,14 @@ export interface SendRequest { * Optional provenance tag copied to the resulting user.message event. Supported values are `system`, `command-*`, and `schedule-*`. */ source?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; agentMode?: SendAgentMode; /** * Custom HTTP headers to include in outbound model requests for this turn. Merged with session-level provider headers; per-turn headers augment and overwrite session-level headers with the same key. */ requestHeaders?: { - [k: string]: string; + [k: string]: string | undefined; }; /** * W3C Trace Context traceparent header for distributed tracing of this agent turn @@ -4915,7 +4920,7 @@ export interface SessionBulkDeleteResult { * Map of sessionId -> bytes freed by removing the session's workspace directory. Sessions whose deletion failed are omitted from this map (failures are logged on the server but not surfaced per-id; check the map for absent IDs to detect them). */ freedBytes: { - [k: string]: number; + [k: string]: number | undefined; }; } /** @@ -5302,7 +5307,7 @@ export interface SessionFsSqliteQueryRequest { * Optional named bind parameters */ params?: { - [k: string]: string | number | null; + [k: string]: (string | number | null) | undefined; }; } /** @@ -5316,7 +5321,7 @@ export interface SessionFsSqliteQueryResult { * For SELECT: array of row objects. For others: empty array. */ rows: { - [k: string]: unknown; + [k: string]: unknown | undefined; }[]; /** * Column names from the result set @@ -5866,7 +5871,7 @@ export interface SessionSizes { * Map of sessionId -> on-disk size in bytes for the session's workspace directory */ sizes: { - [k: string]: number; + [k: string]: number | undefined; }; } /** @@ -6061,7 +6066,7 @@ export interface SessionUpdateOptionsParams { * Map of feature-flag IDs to their boolean enabled state. */ featureFlags?: { - [k: string]: boolean; + [k: string]: boolean | undefined; }; /** * Whether experimental capabilities are enabled. @@ -6071,7 +6076,7 @@ export interface SessionUpdateOptionsParams { * Custom model-provider configuration (BYOK). Opaque shape; see `ProviderConfig` in the runtime. */ provider?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Absolute working-directory path for shell tools. @@ -6101,7 +6106,7 @@ export interface SessionUpdateOptionsParams { * Sandbox configuration shape; opaque to SDK consumers. See `SandboxConfig` in the runtime. */ sandboxConfig?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Whether interactive shell sessions are logged. @@ -6869,7 +6874,7 @@ export interface TelemetrySetFeatureOverridesRequest { * Override key/value pairs to attach to subsequent telemetry events from this session. Replaces any previously-set overrides. */ features: { - [k: string]: string; + [k: string]: string | undefined; }; } /** @@ -6895,7 +6900,7 @@ export interface Tool { * JSON Schema for the tool's input parameters */ parameters?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Optional instructions for how to use this tool effectively @@ -7071,7 +7076,7 @@ export interface UIElicitationSchema { * Form field definitions, keyed by field name */ properties: { - [k: string]: UIElicitationSchemaProperty; + [k: string]: UIElicitationSchemaProperty | undefined; }; /** * List of required field names @@ -7363,7 +7368,7 @@ export interface UIHandlePendingSamplingRequest { * via the `definition` "UIHandlePendingSamplingResponse". */ export interface UIHandlePendingSamplingResponse { - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Request ID of a pending `user_input.requested` event and the user's response. @@ -7454,7 +7459,7 @@ export interface UsageGetMetricsResult { * Session-wide per-token-type accumulated token counts */ tokenDetails?: { - [k: string]: UsageMetricsTokenDetail; + [k: string]: UsageMetricsTokenDetail | undefined; }; /** * Total time spent in model API calls (milliseconds) @@ -7469,7 +7474,7 @@ export interface UsageGetMetricsResult { * Per-model token and request metrics, keyed by model identifier */ modelMetrics: { - [k: string]: UsageMetricsModelMetric; + [k: string]: UsageMetricsModelMetric | undefined; }; /** * Currently active model identifier @@ -7540,7 +7545,7 @@ export interface UsageMetricsModelMetric { * Token count details per type */ tokenDetails?: { - [k: string]: UsageMetricsModelMetricTokenDetail; + [k: string]: UsageMetricsModelMetricTokenDetail | undefined; }; } /** diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts index f72c2dbb0..2e501591f 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -262,7 +262,7 @@ export type ElicitationCompletedAction = "accept" | "decline" | "cancel"; /** * Schema for the `ElicitationCompletedContent` type. */ -export type ElicitationCompletedContent = string | number | boolean | string[]; +export type ElicitationCompletedContent = (string | number | boolean | string[]) | undefined; /** * Source-defined JSON payload for the custom notification */ @@ -273,7 +273,7 @@ export type CustomNotificationPayload = | null | unknown[] | { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * The user's auto-mode-switch choice @@ -1276,7 +1276,7 @@ export interface ShutdownData { * Per-model usage breakdown, keyed by model identifier */ modelMetrics: { - [k: string]: ShutdownModelMetric; + [k: string]: ShutdownModelMetric | undefined; }; /** * Unix timestamp (milliseconds) when the session started @@ -1291,7 +1291,7 @@ export interface ShutdownData { * Session-wide per-token-type accumulated token counts */ tokenDetails?: { - [k: string]: ShutdownTokenDetail; + [k: string]: ShutdownTokenDetail | undefined; }; /** * Tool definitions token count at shutdown @@ -1336,7 +1336,7 @@ export interface ShutdownModelMetric { * Token count details per type */ tokenDetails?: { - [k: string]: ShutdownModelMetricTokenDetail; + [k: string]: ShutdownModelMetricTokenDetail | undefined; }; /** * Accumulated nano-AI units cost for this model @@ -2306,7 +2306,7 @@ export interface AssistantMessageToolRequest { * Arguments to pass to the tool, format depends on the tool */ arguments?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Resolved intention summary describing what this specific call does @@ -2553,7 +2553,7 @@ export interface AssistantUsageData { * Per-quota resource usage snapshots, keyed by quota identifier */ quotaSnapshots?: { - [k: string]: AssistantUsageQuotaSnapshot; + [k: string]: AssistantUsageQuotaSnapshot | undefined; }; /** * Reasoning effort level used for model calls, if applicable (e.g. "none", "low", "medium", "high", "xhigh", "max") @@ -2777,7 +2777,7 @@ export interface ToolUserRequestedData { * Arguments for the tool invocation */ arguments?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Unique identifier for this tool call @@ -2826,7 +2826,7 @@ export interface ToolExecutionStartData { * Arguments passed to the tool */ arguments?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Name of the MCP server hosting this tool, when the tool is an MCP tool @@ -3005,7 +3005,7 @@ export interface ToolExecutionCompleteData { * Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts) */ toolTelemetry?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Identifier for the agent loop turn this tool was invoked in, matching the corresponding assistant.turn_start event @@ -3584,7 +3584,7 @@ export interface HookStartData { * Input data passed to the hook */ input?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; } /** @@ -3634,7 +3634,7 @@ export interface HookEndData { * Output data produced by the hook */ output?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Whether the hook completed successfully @@ -3711,7 +3711,7 @@ export interface SystemMessageMetadata { * Template variables used when constructing the prompt */ variables?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; } /** @@ -4063,7 +4063,7 @@ export interface PermissionRequestMcp { * Arguments to pass to the MCP tool */ args?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Permission kind discriminator @@ -4150,7 +4150,7 @@ export interface PermissionRequestCustomTool { * Arguments to pass to the custom tool */ args?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Permission kind discriminator @@ -4185,7 +4185,7 @@ export interface PermissionRequestHook { * Arguments of the tool call being gated */ toolArgs?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Tool call ID that triggered this permission request @@ -4411,7 +4411,7 @@ export interface PermissionPromptRequestCustomTool { * Arguments to pass to the custom tool */ args?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Prompt kind discriminator @@ -4464,7 +4464,7 @@ export interface PermissionPromptRequestHook { * Arguments of the tool call being gated */ toolArgs?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Tool call ID that triggered this permission request @@ -4947,7 +4947,7 @@ export interface ElicitationRequestedData { * URL to open in the user's browser (url mode only) */ url?: string; - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * JSON Schema describing the form fields to present to the user (form mode only) @@ -4957,7 +4957,7 @@ export interface ElicitationRequestedSchema { * Form field definitions, keyed by field name */ properties: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * List of required field names @@ -5007,7 +5007,7 @@ export interface ElicitationCompletedData { * The submitted form data when action is 'accept'; keys match the requested schema fields */ content?: { - [k: string]: ElicitationCompletedContent; + [k: string]: ElicitationCompletedContent | undefined; }; /** * Request ID of the resolved elicitation request; clients should dismiss any UI for this request @@ -5060,7 +5060,7 @@ export interface SamplingRequestedData { * Name of the MCP server that initiated the sampling request */ serverName: string; - [k: string]: unknown; + [k: string]: unknown | undefined; } /** * Session event "sampling.completed". Sampling request completion notification signaling UI dismissal @@ -5258,7 +5258,7 @@ export interface CustomNotificationData { * Optional source-defined string identifiers describing the payload subject */ export interface CustomNotificationSubject { - [k: string]: string; + [k: string]: string | undefined; } /** * Session event "external_tool.requested". External tool invocation request for client-side tool execution @@ -5298,7 +5298,7 @@ export interface ExternalToolRequestedData { * Arguments to pass to the external tool */ arguments?: { - [k: string]: unknown; + [k: string]: unknown | undefined; }; /** * Unique identifier for this request; used to respond via session.respondToExternalTool() diff --git a/nodejs/src/sessionFsProvider.ts b/nodejs/src/sessionFsProvider.ts index a2da12307..7e959849e 100644 --- a/nodejs/src/sessionFsProvider.ts +++ b/nodejs/src/sessionFsProvider.ts @@ -95,6 +95,22 @@ export interface SessionFsProvider { sqlite?: SessionFsSqliteProvider; } +function normalizeSqliteParams( + params?: Record +): Record | undefined { + if (!params) { + return undefined; + } + + const normalized: Record = {}; + for (const [key, value] of Object.entries(params)) { + if (value !== undefined) { + normalized[key] = value; + } + } + return normalized; +} + /** * Wraps a {@link SessionFsProvider} into the {@link SessionFsHandler} * interface expected by the SDK, converting thrown errors into @@ -196,7 +212,11 @@ export function createSessionFsAdapter(provider: SessionFsProvider): SessionFsHa if (!provider.sqlite) { throw new Error("SQLite is not supported by this provider"); } - const result = await provider.sqlite.query(queryType, query, bindParams); + const result = await provider.sqlite.query( + queryType, + query, + normalizeSqliteParams(bindParams) + ); return result ?? { rows: [], columns: [], rowsAffected: 0 }; }, sqliteExists: async () => { diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py index c821c042a..b72bd97ad 100644 --- a/python/copilot/generated/rpc.py +++ b/python/copilot/generated/rpc.py @@ -15510,6 +15510,7 @@ def rpc_to_dict(x: RPC) -> Any: SessionWorkingDirectoryContextHostType = SessionContextHostType TaskInfoExecutionMode = TaskExecutionMode TaskInfoStatus = TaskStatus +TaskInfoType = TaskAgentProgressType TaskProgress = TaskProgressClass TaskShellProgress = None diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs index 7596405bd..7a6d4276b 100644 --- a/rust/src/generated/api_types.rs +++ b/rust/src/generated/api_types.rs @@ -10,7 +10,8 @@ use super::session_events::{ AbortReason, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, ReasoningSummary, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval, }; -use crate::types::{RequestId, SessionEvent, SessionId}; +use crate::types::SessionEvent; +use crate::types::{RequestId, SessionId}; /// JSON-RPC method name constants. pub mod rpc_methods { @@ -2687,7 +2688,7 @@ pub struct NameSetRequest { } /// Schema for the `PendingPermissionRequest` type. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PendingPermissionRequest { /// The user-facing permission prompt details (commands, write, read, mcp, url, memory, custom-tool, path, hook) @@ -2950,7 +2951,7 @@ pub struct PermissionDecisionApproved { } /// Schema for the `PermissionDecisionApprovedForSession` type. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApprovedForSession { /// The approval to add as a session-scoped rule @@ -2960,7 +2961,7 @@ pub struct PermissionDecisionApprovedForSession { } /// Schema for the `PermissionDecisionApprovedForLocation` type. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PermissionDecisionApprovedForLocation { /// The approval to persist for this location diff --git a/rust/src/session.rs b/rust/src/session.rs index 970381724..d533dbc44 100644 --- a/rust/src/session.rs +++ b/rust/src/session.rs @@ -545,6 +545,8 @@ impl Session { message: message.to_string(), level, ephemeral: opts.ephemeral, + r#type: None, + tip: None, url: None, }; self.rpc().log(request).await?; diff --git a/rust/src/session_fs_dispatch.rs b/rust/src/session_fs_dispatch.rs index 4a09666f4..f77c9aa53 100644 --- a/rust/src/session_fs_dispatch.rs +++ b/rust/src/session_fs_dispatch.rs @@ -350,7 +350,7 @@ pub(crate) async fn sqlite_query( columns: result.columns, rows: result.rows, rows_affected: result.rows_affected, - last_insert_rowid: result.last_insert_rowid.map(|v| v as f64), + last_insert_rowid: result.last_insert_rowid, error: None, }, Ok(None) => GeneratedSqliteQueryResult { diff --git a/rust/tests/e2e/compaction.rs b/rust/tests/e2e/compaction.rs index ef7eaea80..b4724f3f9 100644 --- a/rust/tests/e2e/compaction.rs +++ b/rust/tests/e2e/compaction.rs @@ -65,7 +65,7 @@ async fn should_trigger_compaction_with_low_threshold_and_emit_events() { .expect("compaction start task") .typed_data::() .expect("compaction start data"); - assert!(start.conversation_tokens.unwrap_or_default() > 0.0); + assert!(start.conversation_tokens.unwrap_or_default() > 0); let complete = compaction_completed .await @@ -79,7 +79,7 @@ async fn should_trigger_compaction_with_low_threshold_and_emit_events() { .as_ref() .and_then(|usage| usage.input_tokens) .unwrap_or_default() - > 0.0 + > 0 ); let summary = complete.summary_content.unwrap_or_default().to_lowercase(); assert!(summary.contains("")); diff --git a/rust/tests/e2e/event_fidelity.rs b/rust/tests/e2e/event_fidelity.rs index c23ae6eff..61d1f4f1f 100644 --- a/rust/tests/e2e/event_fidelity.rs +++ b/rust/tests/e2e/event_fidelity.rs @@ -161,9 +161,9 @@ async fn should_emit_session_usage_info_event_after_model_call() { .find(|event| event.parsed_type() == SessionEventType::SessionUsageInfo) .and_then(|event| event.typed_data::()) .expect("session.usage_info"); - assert!(usage.current_tokens > 0.0); - assert!(usage.messages_length > 0.0); - assert!(usage.token_limit > 0.0); + assert!(usage.current_tokens > 0); + assert!(usage.messages_length > 0); + assert!(usage.token_limit > 0); session.disconnect().await.expect("disconnect session"); client.stop().await.expect("stop client"); diff --git a/rust/tests/e2e/mode_handlers.rs b/rust/tests/e2e/mode_handlers.rs index 1c997fccf..5751afbca 100644 --- a/rust/tests/e2e/mode_handlers.rs +++ b/rust/tests/e2e/mode_handlers.rs @@ -215,7 +215,7 @@ async fn should_invoke_auto_mode_switch_handler_when_rate_limited() { .typed_data::() .is_some_and(|data| { data.error_code.as_deref() == Some("user_weekly_rate_limited") - && data.retry_after_seconds == Some(1.0) + && data.retry_after_seconds == Some(1) }) }, )); @@ -265,7 +265,10 @@ async fn should_invoke_auto_mode_switch_handler_when_rate_limited() { .typed_data::() .expect("typed requested event"); assert_eq!(requested_data.error_code, error_code); - assert_eq!(requested_data.retry_after_seconds, retry_after_seconds); + assert_eq!( + requested_data.retry_after_seconds.map(|value| value as f64), + retry_after_seconds + ); let completed = completed_event.await.expect("completed task"); let completed_data = completed diff --git a/rust/tests/e2e/permissions.rs b/rust/tests/e2e/permissions.rs index 30b7a7d85..8d7834768 100644 --- a/rust/tests/e2e/permissions.rs +++ b/rust/tests/e2e/permissions.rs @@ -393,7 +393,10 @@ async fn should_short_circuit_permission_handler_when_set_approve_all_enabled() let set_result = session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: true }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: true, + source: None, + }) .await .expect("set approve all"); assert!(set_result.success); @@ -420,7 +423,10 @@ async fn should_short_circuit_permission_handler_when_set_approve_all_enabled() let reset_result = session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: false }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: false, + source: None, + }) .await .expect("reset approve all"); assert!(reset_result.success); diff --git a/rust/tests/e2e/rpc_additional_edge_cases.rs b/rust/tests/e2e/rpc_additional_edge_cases.rs index c56b39844..35fa9265e 100644 --- a/rust/tests/e2e/rpc_additional_edge_cases.rs +++ b/rust/tests/e2e/rpc_additional_edge_cases.rs @@ -338,7 +338,7 @@ async fn usage_get_metrics_on_fresh_session_returns_zero_tokens() { assert_eq!(metrics.last_call_input_tokens, 0); assert_eq!(metrics.last_call_output_tokens, 0); assert_eq!(metrics.total_user_requests, 0); - assert!(metrics.session_start_time > 0); + assert!(!metrics.session_start_time.is_empty()); session.disconnect().await.expect("disconnect session"); client.stop().await.expect("stop client"); @@ -396,7 +396,10 @@ async fn permissions_set_approve_all_toggle_round_trips() { session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: true }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: true, + source: None, + }) .await .expect("enable approve all") .success @@ -405,7 +408,10 @@ async fn permissions_set_approve_all_toggle_round_trips() { session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: true }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: true, + source: None, + }) .await .expect("enable approve all again") .success @@ -414,7 +420,10 @@ async fn permissions_set_approve_all_toggle_round_trips() { session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: false }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: false, + source: None, + }) .await .expect("disable approve all") .success diff --git a/rust/tests/e2e/rpc_server.rs b/rust/tests/e2e/rpc_server.rs index d1508541b..b10f4ad96 100644 --- a/rust/tests/e2e/rpc_server.rs +++ b/rust/tests/e2e/rpc_server.rs @@ -25,7 +25,7 @@ async fn should_call_rpc_ping_with_typed_params_and_result() { .expect("ping"); assert_eq!(result.message, "pong: typed rpc test"); - assert!(result.timestamp >= 0); + assert!(!result.timestamp.is_empty()); client.stop().await.expect("stop client"); }) }, diff --git a/rust/tests/e2e/rpc_session_state.rs b/rust/tests/e2e/rpc_session_state.rs index e246e6a03..5dee2c8a3 100644 --- a/rust/tests/e2e/rpc_session_state.rs +++ b/rust/tests/e2e/rpc_session_state.rs @@ -585,12 +585,15 @@ async fn should_call_session_usage_and_permission_rpcs() { .expect("create session"); let metrics = session.rpc().usage().get_metrics().await.expect("metrics"); - assert!(metrics.session_start_time > 0); + assert!(!metrics.session_start_time.is_empty()); assert!( session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: true }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: true, + source: None, + }) .await .expect("set approve all") .success @@ -607,7 +610,10 @@ async fn should_call_session_usage_and_permission_rpcs() { session .rpc() .permissions() - .set_approve_all(PermissionsSetApproveAllRequest { enabled: false }) + .set_approve_all(PermissionsSetApproveAllRequest { + enabled: false, + source: None, + }) .await .expect("disable approve all"); diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 199a79913..558367a6f 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -377,7 +377,7 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: * Emit C# data-annotation attributes for a JSON Schema property. * Returns an array of attribute lines (without trailing newlines). */ -function emitDataAnnotations(schema: JSONSchema7, indent: string): string[] { +function emitDataAnnotations(schema: JSONSchema7, indent: string, csharpType: string): string[] { const attrs: string[] = []; const format = schema.format; @@ -400,27 +400,6 @@ function emitDataAnnotations(schema: JSONSchema7, indent: string): string[] { attrs.push(`${indent}[Base64String]`); } - // [Range] for minimum/maximum - const hasMin = typeof schema.minimum === "number"; - const hasMax = typeof schema.maximum === "number"; - if (hasMin || hasMax) { - const namedArgs: string[] = []; - if (schema.exclusiveMinimum === true) namedArgs.push("MinimumIsExclusive = true"); - if (schema.exclusiveMaximum === true) namedArgs.push("MaximumIsExclusive = true"); - const namedSuffix = namedArgs.length > 0 ? `, ${namedArgs.join(", ")}` : ""; - if (schema.type === "integer") { - // Use Range(double, double) for AOT/trimming compatibility. - // The Range(Type, string, string) overload uses TypeConverter which triggers IL2026. - const min = hasMin ? String(schema.minimum) : "long.MinValue"; - const max = hasMax ? String(schema.maximum) : "long.MaxValue"; - attrs.push(`${indent}[Range((double)${min}, (double)${max}${namedSuffix})]`); - } else { - const min = hasMin ? String(schema.minimum) : "double.MinValue"; - const max = hasMax ? String(schema.maximum) : "double.MaxValue"; - attrs.push(`${indent}[Range(${min}, ${max}${namedSuffix})]`); - } - } - // [RegularExpression] for pattern constraints on non-regex-format properties if (format !== "regex" && typeof schema.pattern === "string") { attrs.push(`${indent}[RegularExpression("${escapeCSharpStringLiteral(schema.pattern)}")]`); @@ -757,7 +736,7 @@ function generateFlattenedBooleanDiscriminatedClass( lines.push(""); lines.push(...xmlDocPropertyComment(info.schema.description, propName, " ")); - lines.push(...emitDataAnnotations(info.schema, " ")); + lines.push(...emitDataAnnotations(info.schema, " ", csharpType)); if (isSchemaDeprecated(info.schema)) pushObsoleteAttributes(lines, " "); if (isDurationProperty(info.schema)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); @@ -860,7 +839,7 @@ function generateDerivedClass( const csharpType = propertyResolver(prop, className, csharpName, isReq, knownTypes, nestedClasses, enumOutput); lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); - lines.push(...emitDataAnnotations(prop, " ")); + lines.push(...emitDataAnnotations(prop, " ", csharpType)); if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); @@ -1085,7 +1064,7 @@ function generateNestedClass( const csharpType = resolveSessionPropertyType(prop, className, csharpName, isReq, knownTypes, nestedClasses, enumOutput); lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); - lines.push(...emitDataAnnotations(prop, " ")); + lines.push(...emitDataAnnotations(prop, " ", csharpType)); if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); @@ -1228,7 +1207,7 @@ function generateDataClass(variant: EventVariant, knownTypes: Map; experimentalTypeNames?: Iterable; + nonDefaultableTypes?: Iterable; } = {}, ): RustCodegenCtx { return { structs: [], enums: [], generatedNames: new Set(), - nonDefaultableTypes: new Set(), + nonDefaultableTypes: new Set(options.nonDefaultableTypes ?? []), experimentalTypeNames: new Set(options.experimentalTypeNames ?? []), definitions, unionDiscriminatorProperties: @@ -1153,6 +1154,16 @@ export function generateSessionEventsCode(schema: JSONSchema7): string { return out.join("\n"); } +function collectNonDefaultableRustTypeNames(code: string): Set { + const names = new Set(); + const pattern = + /#\[derive\(Debug, Clone, Serialize, Deserialize\)\](?:\r?\n#\[serde\([^\n]+\)\])*\r?\npub (?:struct|enum) (\w+)/g; + for (const match of code.matchAll(pattern)) { + names.add(match[1]); + } + return names; +} + // ── API types generation ──────────────────────────────────────────────────── function collectRpcMethods( @@ -1267,12 +1278,15 @@ function isNullableParamsSchema( return !!resolved && !!getNullableInner(resolved); } -function generateApiTypesCode(apiSchema: ApiSchema): string { +function generateApiTypesCode( + apiSchema: ApiSchema, + nonDefaultableTypes: Iterable = [], +): string { const definitions = collectDefinitions(apiSchema as Record); const defCollections = collectDefinitionCollections( apiSchema as Record, ); - const ctx = makeCtx(defCollections); + const ctx = makeCtx(defCollections, { nonDefaultableTypes }); // Collect all RPC methods before emitting shared definitions so method stability // can propagate to referenced data types. @@ -2011,7 +2025,10 @@ async function generate(): Promise { // Generate API types console.log("Generating api_types.rs..."); - const apiTypesCode = generateApiTypesCode(apiSchemaForGeneration); + const apiTypesCode = generateApiTypesCode( + apiSchemaForGeneration, + collectNonDefaultableRustTypeNames(sessionEventsCode), + ); const apiTypesPath = path.join(GENERATED_DIR, "api_types.rs"); await fs.writeFile(apiTypesPath, apiTypesCode, "utf-8"); await rustfmt(apiTypesPath); diff --git a/scripts/codegen/typescript.ts b/scripts/codegen/typescript.ts index b3a929bf3..3afaec395 100644 --- a/scripts/codegen/typescript.ts +++ b/scripts/codegen/typescript.ts @@ -345,6 +345,7 @@ async function generateSessionEvents(schemaPath?: string): Promise { */`, style: { semi: true, singleQuote: false, trailingComma: "all" }, additionalProperties: false, + strictIndexSignatures: true, }); const annotatedTs = annotateTypeScriptTypes(ts, experimentalDefinitionNames(definitionCollections), TS_EXPERIMENTAL_JSDOC); @@ -582,6 +583,7 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js"; const compiled = await compile(normalizeSchemaForTypeScript(schemaForCompile), "_RpcSchemaRoot", { bannerComment: "", additionalProperties: false, + strictIndexSignatures: true, unreachableDefinitions: true, }); From 20256b19bd2ad17af331e2cf59b31f16787aaefb Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 22:44:01 -0400 Subject: [PATCH 3/6] Address SDK review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Generated/SessionEvents.cs | 3 +- dotnet/test/E2E/ModeHandlersE2ETests.cs | 2 +- go/rpc/generated_rpc_union_test.go | 32 ++++++++++++++++ go/rpc/zrpc_encoding.go | 4 +- nodejs/test/session-event-codegen.test.ts | 38 +++++++++++++++++++ scripts/codegen/csharp.ts | 45 ++++++++++++++--------- scripts/codegen/go.ts | 26 ++++++++++--- 7 files changed, 121 insertions(+), 29 deletions(-) diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 534bd3bba..8a109040c 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -2945,10 +2945,9 @@ public sealed partial class AutoModeSwitchRequestedData public required string RequestId { get; set; } /// Seconds until the rate limit resets, when known. Lets clients render a humanized reset time alongside the prompt. - [JsonConverter(typeof(MillisecondsTimeSpanConverter))] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonPropertyName("retryAfterSeconds")] - public TimeSpan? RetryAfterSeconds { get; set; } + public long? RetryAfterSeconds { get; set; } } /// Auto mode switch completion notification. diff --git a/dotnet/test/E2E/ModeHandlersE2ETests.cs b/dotnet/test/E2E/ModeHandlersE2ETests.cs index 78b65c0ca..0af54c4fd 100644 --- a/dotnet/test/E2E/ModeHandlersE2ETests.cs +++ b/dotnet/test/E2E/ModeHandlersE2ETests.cs @@ -103,7 +103,7 @@ public async Task Should_Invoke_Auto_Mode_Switch_Handler_When_Rate_Limited() }, }); - var expectedRetryAfter = TimeSpan.FromMilliseconds(1); + const long expectedRetryAfter = 1; var requestedEventTask = GetNextEventOfTypeAllowingRateLimitAsync( session, evt => evt.Data.ErrorCode == "user_weekly_rate_limited" && evt.Data.RetryAfterSeconds == expectedRetryAfter, diff --git a/go/rpc/generated_rpc_union_test.go b/go/rpc/generated_rpc_union_test.go index 8a85ee398..2cdb2f6ef 100644 --- a/go/rpc/generated_rpc_union_test.go +++ b/go/rpc/generated_rpc_union_test.go @@ -133,6 +133,38 @@ func TestMcpServerConfigJSONUnion(t *testing.T) { } } +func TestTaskProgressUnmarshalsTaskAgentProgressVariants(t *testing.T) { + var agentProgress TaskProgress + if err := json.Unmarshal([]byte(`{"type":"agent","recentActivity":[],"latestIntent":"Summarizing"}`), &agentProgress); err != nil { + t.Fatalf("unmarshal agent task progress: %v", err) + } + agentValue, ok := agentProgress.TaskAgentProgress.(*TaskAgentProgressAgent) + if !ok { + t.Fatalf("agent task progress = %T, want *TaskAgentProgressAgent", agentProgress.TaskAgentProgress) + } + if agentValue.LatestIntent == nil || *agentValue.LatestIntent != "Summarizing" { + t.Fatalf("agent latest intent = %v, want Summarizing", agentValue.LatestIntent) + } + if agentProgress.TaskShellProgress != nil { + t.Fatalf("agent task shell progress = %#v, want nil", *agentProgress.TaskShellProgress) + } + + var shellProgress TaskProgress + if err := json.Unmarshal([]byte(`{"type":"shell","recentOutput":"building","pid":123}`), &shellProgress); err != nil { + t.Fatalf("unmarshal shell task progress: %v", err) + } + shellValue, ok := shellProgress.TaskAgentProgress.(*TaskAgentProgressShell) + if !ok { + t.Fatalf("shell task progress = %T, want *TaskAgentProgressShell", shellProgress.TaskAgentProgress) + } + if shellValue.RecentOutput != "building" { + t.Fatalf("shell recent output = %q, want building", shellValue.RecentOutput) + } + if shellValue.Pid == nil || *shellValue.Pid != 123 { + t.Fatalf("shell pid = %v, want 123", shellValue.Pid) + } +} + func TestCommandsInvokeUnmarshalsSlashCommandInvocationResult(t *testing.T) { clientToServerReader, clientToServerWriter := io.Pipe() serverToClientReader, serverToClientWriter := io.Pipe() diff --git a/go/rpc/zrpc_encoding.go b/go/rpc/zrpc_encoding.go index 617550389..a0e0da3e0 100644 --- a/go/rpc/zrpc_encoding.go +++ b/go/rpc/zrpc_encoding.go @@ -2182,8 +2182,8 @@ func (r *TaskProgress) UnmarshalJSON(data []byte) error { return nil } { - var value TaskAgentProgress - if err := json.Unmarshal(data, &value); err == nil { + value, err := unmarshalTaskAgentProgress(data) + if err == nil { *r = TaskProgress{TaskAgentProgress: value} return nil } diff --git a/nodejs/test/session-event-codegen.test.ts b/nodejs/test/session-event-codegen.test.ts index ffb8936e4..86c76f71b 100644 --- a/nodejs/test/session-event-codegen.test.ts +++ b/nodejs/test/session-event-codegen.test.ts @@ -171,6 +171,44 @@ describe("session event codegen", () => { ); }); + it("keeps C# seconds-valued duration members numeric", () => { + const schema: JSONSchema7 = { + definitions: { + SessionEvent: { + anyOf: [ + { + type: "object", + required: ["type", "data"], + properties: { + type: { const: "session.synthetic" }, + data: { + type: "object", + properties: { + retryAfterSeconds: { + type: "integer", + format: "duration", + description: + "Seconds until the rate limit resets, when known.", + }, + }, + }, + }, + }, + ], + }, + }, + }; + + const csharpCode = generateCSharpSessionEventsCode(schema); + + expect(csharpCode).toContain( + '[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]\n [JsonPropertyName("retryAfterSeconds")]\n public long? RetryAfterSeconds { get; set; }' + ); + expect(csharpCode).not.toContain( + '[JsonConverter(typeof(MillisecondsTimeSpanConverter))]\n [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]\n [JsonPropertyName("retryAfterSeconds")]' + ); + }); + it("collapses redundant callable wrapper lambdas", () => { const schema: JSONSchema7 = { definitions: { diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts index 558367a6f..8fd6b6f58 100644 --- a/scripts/codegen/csharp.ts +++ b/scripts/codegen/csharp.ts @@ -228,6 +228,10 @@ function toCSharpPropertyName(propName: string, schema: JSONSchema7): string { return toPascalCase(isDurationProperty(schema) ? stripDurationMillisecondsSuffix(propName) : propName); } +function isSecondsDurationPropertyName(propName: string | undefined): boolean { + return propName !== undefined && /seconds$/i.test(propName); +} + function typeToClassName(typeName: string): string { return splitCSharpIdentifierParts(typeName).map(toPascalCasePart).join(""); } @@ -304,11 +308,11 @@ function localRequestVariableName(paramEntries: [string, JSONSchema7Definition][ return hasRequestParameter || paramEntries.some(([name]) => name === "request") ? "rpcRequest" : "request"; } -function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: Map): string { +function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: Map, propName?: string): string { const nullableInner = getNullableInner(schema); if (nullableInner) { // Pass required=true to get the base type, then add "?" for nullable - return schemaTypeToCSharp(nullableInner, true, knownTypes) + "?"; + return schemaTypeToCSharp(nullableInner, true, knownTypes, propName) + "?"; } if (schema.$ref) { const refName = schema.$ref.split("/").pop()!; @@ -329,7 +333,7 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: return "string?"; } if (nonNullTypes.length === 1 && (nonNullTypes[0] === "number" || nonNullTypes[0] === "integer")) { - if (format === "duration") { + if (format === "duration" && !isSecondsDurationPropertyName(propName)) { return "TimeSpan?"; } if (nonNullTypes[0] === "integer") { @@ -345,7 +349,7 @@ function schemaTypeToCSharp(schema: JSONSchema7, required: boolean, knownTypes: return required ? "string" : "string?"; } if (type === "number" || type === "integer") { - if (format === "duration") { + if (format === "duration" && !isSecondsDurationPropertyName(propName)) { return required ? "TimeSpan" : "TimeSpan?"; } if (type === "integer") { @@ -424,11 +428,12 @@ function emitDataAnnotations(schema: JSONSchema7, indent: string, csharpType: st /** * Returns true when a TimeSpan-typed property needs a [JsonConverter] attribute. * - * NOTE: The runtime schema uses `format: "duration"` on numeric (integer/number) fields - * to mean "a duration value expressed in milliseconds". This differs from the JSON Schema - * spec, where `format: "duration"` denotes an ISO 8601 duration string (e.g. "PT1H30M"). - * The generator and runtime agree on this convention, so we map these to TimeSpan with a - * milliseconds-based JSON converter rather than expecting ISO 8601 strings. + * NOTE: The runtime schema generally uses `format: "duration"` on numeric (integer/number) + * fields to mean "a duration value expressed in milliseconds". This differs from the JSON + * Schema spec, where `format: "duration"` denotes an ISO 8601 duration string (e.g. + * "PT1H30M"). The generator and runtime agree on this convention, so we map millisecond + * fields to TimeSpan with a milliseconds-based JSON converter rather than expecting ISO + * 8601 strings. Seconds-suffixed fields stay numeric because their wire value is seconds. */ function isDurationProperty(schema: JSONSchema7): boolean { const nullableInner = getNullableInner(schema); @@ -447,6 +452,10 @@ function isDurationProperty(schema: JSONSchema7): boolean { return false; } +function isMillisecondsDurationProperty(propName: string | undefined, schema: JSONSchema7): boolean { + return isDurationProperty(schema) && !isSecondsDurationPropertyName(propName); +} + const COPYRIGHT = `/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. @@ -738,7 +747,7 @@ function generateFlattenedBooleanDiscriminatedClass( lines.push(...xmlDocPropertyComment(info.schema.description, propName, " ")); lines.push(...emitDataAnnotations(info.schema, " ", csharpType)); if (isSchemaDeprecated(info.schema)) pushObsoleteAttributes(lines, " "); - if (isDurationProperty(info.schema)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); + if (isMillisecondsDurationProperty(propName, info.schema)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); lines.push(` [JsonPropertyName("${propName}")]`); const reqMod = isReq && !csharpType.endsWith("?") ? "required " : ""; @@ -841,7 +850,7 @@ function generateDerivedClass( lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); lines.push(...emitDataAnnotations(prop, " ", csharpType)); if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); - if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); + if (isMillisecondsDurationProperty(propName, prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); lines.push(` [JsonPropertyName("${propName}")]`); const reqMod = isReq && !csharpType.endsWith("?") ? "required " : ""; @@ -1066,7 +1075,7 @@ function generateNestedClass( lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); lines.push(...emitDataAnnotations(prop, " ", csharpType)); if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); - if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); + if (isMillisecondsDurationProperty(propName, prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`); lines.push(` [JsonPropertyName("${propName}")]`); const reqMod = isReq && !csharpType.endsWith("?") ? "required " : ""; @@ -1178,7 +1187,7 @@ function resolveSessionPropertyType( ); return isRequired ? `IDictionary` : `IDictionary?`; } - return schemaTypeToCSharp(propSchema, isRequired, knownTypes); + return schemaTypeToCSharp(propSchema, isRequired, knownTypes, propName); } function generateDataClass(variant: EventVariant, knownTypes: Map, nestedClasses: Map, enumOutput: string[]): string { @@ -1209,7 +1218,7 @@ function generateDataClass(variant: EventVariant, knownTypes: Map` : `IDictionary?`; } - return schemaTypeToCSharp(schema, isRequired, rpcKnownTypes); + return schemaTypeToCSharp(schema, isRequired, rpcKnownTypes, propName); } function emitRpcClass( @@ -1594,7 +1603,7 @@ function emitRpcClass( lines.push(...xmlDocPropertyComment(prop.description, propName, " ")); lines.push(...emitDataAnnotations(prop, " ", csharpType)); if (isSchemaDeprecated(prop)) pushObsoleteAttributes(lines, " "); - if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); + if (isMillisecondsDurationProperty(propName, prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`); lines.push(` [JsonPropertyName("${propName}")]`); let defaultVal = ""; @@ -1792,7 +1801,7 @@ function emitServerInstanceMethod( : toPascalCase(pName); const csType = requestClassName ? resolveRpcType(jsonSchema, isReq, requestClassName, csharpName, classes) - : schemaTypeToCSharp(jsonSchema, isReq, rpcKnownTypes); + : schemaTypeToCSharp(jsonSchema, isReq, rpcKnownTypes, csharpName); sigParams.push(`${csType} ${pName}${isReq ? "" : " = null"}`); bodyAssignments.push(`${csharpName} = ${pName}`); if (requiresArgumentNullCheck(csType, isReq)) { diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts index 217f0e168..03a8da8e8 100644 --- a/scripts/codegen/go.ts +++ b/scripts/codegen/go.ts @@ -2747,19 +2747,33 @@ function emitGoUnionWrapperStruct(typeName: string, schema: JSONSchema7, ctx: Go encodingLines.push(`\t}`); for (const field of fields) { const matchFunction = matchFunctionsByField.get(field.name); + const unmarshalType = goUnionFieldUnmarshalType(field.type); + const unionInfo = goDiscriminatedUnionInfoForType(unmarshalType, ctx); if (matchFunction) { encodingLines.push(`\tif ${matchFunction}(data) {`); - encodingLines.push(`\t\tvar value ${goUnionFieldUnmarshalType(field.type)}`); - encodingLines.push(`\t\tif err := json.Unmarshal(data, &value); err != nil {`); - encodingLines.push(`\t\t\treturn err`); - encodingLines.push(`\t\t}`); + if (unionInfo) { + encodingLines.push(`\t\tvalue, err := ${unionInfo.unmarshalFuncName}(data)`); + encodingLines.push(`\t\tif err != nil {`); + encodingLines.push(`\t\t\treturn err`); + encodingLines.push(`\t\t}`); + } else { + encodingLines.push(`\t\tvar value ${unmarshalType}`); + encodingLines.push(`\t\tif err := json.Unmarshal(data, &value); err != nil {`); + encodingLines.push(`\t\t\treturn err`); + encodingLines.push(`\t\t}`); + } encodingLines.push(`\t\t${goUnionFieldUnmarshalAssignment(typeName, field.name, field.type)}`); encodingLines.push(`\t\treturn nil`); encodingLines.push(`\t}`); } else { encodingLines.push(`\t{`); - encodingLines.push(`\t\tvar value ${goUnionFieldUnmarshalType(field.type)}`); - encodingLines.push(`\t\tif err := json.Unmarshal(data, &value); err == nil {`); + if (unionInfo) { + encodingLines.push(`\t\tvalue, err := ${unionInfo.unmarshalFuncName}(data)`); + encodingLines.push(`\t\tif err == nil {`); + } else { + encodingLines.push(`\t\tvar value ${unmarshalType}`); + encodingLines.push(`\t\tif err := json.Unmarshal(data, &value); err == nil {`); + } encodingLines.push(`\t\t\t${goUnionFieldUnmarshalAssignment(typeName, field.name, field.type)}`); encodingLines.push(`\t\t\treturn nil`); encodingLines.push(`\t\t}`); From 41645c13d2919ad361acd7bea8be8b740ab71f1b Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 23:49:10 -0400 Subject: [PATCH 4/6] Fix SDK compatibility with CLI 1.0.51 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/src/Types.cs | 4 ++-- dotnet/test/E2E/ClientE2ETests.cs | 2 +- dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs | 2 +- nodejs/README.md | 2 +- nodejs/src/client.ts | 4 ++-- nodejs/test/e2e/client.e2e.test.ts | 4 ++-- nodejs/test/e2e/rpc.e2e.test.ts | 2 +- nodejs/test/e2e/rpc_server.e2e.test.ts | 2 +- nodejs/test/e2e/rpc_session_state.e2e.test.ts | 2 +- python/copilot/client.py | 13 ++++++++++--- python/copilot/generated/session_events.py | 6 +++--- python/copilot/session_fs_provider.py | 4 +--- python/e2e/test_client_e2e.py | 4 ++-- python/e2e/test_rpc_e2e.py | 2 +- python/e2e/test_rpc_server_e2e.py | 2 +- python/e2e/test_rpc_session_state_e2e.py | 2 +- rust/src/generated/api_types.rs | 3 +-- rust/src/types.rs | 4 ++-- rust/tests/e2e/client.rs | 2 +- scripts/codegen/python.ts | 8 ++++++-- ..._allow_posttooluse_to_return_modifiedresult.yaml | 2 +- 21 files changed, 42 insertions(+), 34 deletions(-) diff --git a/dotnet/src/Types.cs b/dotnet/src/Types.cs index 18cab63d4..8a0970306 100644 --- a/dotnet/src/Types.cs +++ b/dotnet/src/Types.cs @@ -2795,9 +2795,9 @@ public class PingResponse /// public string Message { get; set; } = string.Empty; /// - /// Server timestamp when the ping was processed. + /// ISO 8601 timestamp when the ping was processed. /// - public long Timestamp { get; set; } + public DateTimeOffset Timestamp { get; set; } /// /// Protocol version supported by the server. /// diff --git a/dotnet/test/E2E/ClientE2ETests.cs b/dotnet/test/E2E/ClientE2ETests.cs index 5aa535334..b8885fb2d 100644 --- a/dotnet/test/E2E/ClientE2ETests.cs +++ b/dotnet/test/E2E/ClientE2ETests.cs @@ -25,7 +25,7 @@ public async Task Should_Start_And_Connect_To_Server(bool useStdio) var pong = await client.PingAsync("test message"); Assert.Equal("pong: test message", pong.Message); - Assert.True(pong.Timestamp >= 0); + Assert.NotEqual(default, pong.Timestamp); await client.StopAsync(); Assert.Equal(ConnectionState.Disconnected, client.State); diff --git a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs index 092012399..238299c02 100644 --- a/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs +++ b/dotnet/test/E2E/RpcAdditionalEdgeCasesE2ETests.cs @@ -151,7 +151,7 @@ public async Task Usage_GetMetrics_On_Fresh_Session_Returns_Zero_Tokens() var metrics = await session.Rpc.Usage.GetMetricsAsync(); // Fresh session = no LLM calls yet. Last-call counters and the user-request count - // must be zero, and SessionStartTime must be a positive epoch (set at create-time). + // must be zero, and SessionStartTime must be populated at create-time. Assert.Equal(0, metrics.LastCallInputTokens); Assert.Equal(0, metrics.LastCallOutputTokens); Assert.Equal(0, metrics.TotalUserRequests); diff --git a/nodejs/README.md b/nodejs/README.md index fd207a0ea..5d0458ad9 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -128,7 +128,7 @@ Create a new conversation session. Resume an existing session. Returns the session with `workspacePath` populated if infinite sessions were enabled. -##### `ping(message?: string): Promise<{ message: string; timestamp: number }>` +##### `ping(message?: string): Promise<{ message: string; timestamp: string }>` Ping the server to check connectivity. diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts index b7f474d1d..6342b6667 100644 --- a/nodejs/src/client.ts +++ b/nodejs/src/client.ts @@ -1031,7 +1031,7 @@ export class CopilotClient { */ async ping( message?: string - ): Promise<{ message: string; timestamp: number; protocolVersion?: number }> { + ): Promise<{ message: string; timestamp: string; protocolVersion?: number }> { if (!this.connection) { throw new Error("Client not connected"); } @@ -1039,7 +1039,7 @@ export class CopilotClient { const result = await this.connection.sendRequest("ping", { message }); return result as { message: string; - timestamp: number; + timestamp: string; protocolVersion?: number; }; } diff --git a/nodejs/test/e2e/client.e2e.test.ts b/nodejs/test/e2e/client.e2e.test.ts index f06468964..906b4fcf4 100644 --- a/nodejs/test/e2e/client.e2e.test.ts +++ b/nodejs/test/e2e/client.e2e.test.ts @@ -22,7 +22,7 @@ describe("Client", () => { const pong = await client.ping("test message"); expect(pong.message).toBe("pong: test message"); - expect(pong.timestamp).toBeGreaterThanOrEqual(0); + expect(Date.parse(pong.timestamp)).not.toBeNaN(); expect(await client.stop()).toHaveLength(0); // No errors on stop expect(client.getState()).toBe("disconnected"); @@ -37,7 +37,7 @@ describe("Client", () => { const pong = await client.ping("test message"); expect(pong.message).toBe("pong: test message"); - expect(pong.timestamp).toBeGreaterThanOrEqual(0); + expect(Date.parse(pong.timestamp)).not.toBeNaN(); expect(await client.stop()).toHaveLength(0); // No errors on stop expect(client.getState()).toBe("disconnected"); diff --git a/nodejs/test/e2e/rpc.e2e.test.ts b/nodejs/test/e2e/rpc.e2e.test.ts index a4c333139..028d4b41a 100644 --- a/nodejs/test/e2e/rpc.e2e.test.ts +++ b/nodejs/test/e2e/rpc.e2e.test.ts @@ -21,7 +21,7 @@ describe("RPC", () => { const result = await client.rpc.ping({ message: "typed rpc test" }); expect(result.message).toBe("pong: typed rpc test"); - expect(typeof result.timestamp).toBe("number"); + expect(Date.parse(result.timestamp)).not.toBeNaN(); await client.stop(); }); diff --git a/nodejs/test/e2e/rpc_server.e2e.test.ts b/nodejs/test/e2e/rpc_server.e2e.test.ts index 59edc7968..68b1beca5 100644 --- a/nodejs/test/e2e/rpc_server.e2e.test.ts +++ b/nodejs/test/e2e/rpc_server.e2e.test.ts @@ -76,7 +76,7 @@ describe("Server-scoped RPC", async () => { await client.start(); const result = await client.ping("typed rpc test"); expect(result.message).toBe("pong: typed rpc test"); - expect(result.timestamp).toBeGreaterThanOrEqual(0); + expect(Date.parse(result.timestamp)).not.toBeNaN(); }); it("should call rpc models list with typed result", async () => { diff --git a/nodejs/test/e2e/rpc_session_state.e2e.test.ts b/nodejs/test/e2e/rpc_session_state.e2e.test.ts index 706c116e4..6af08e42a 100644 --- a/nodejs/test/e2e/rpc_session_state.e2e.test.ts +++ b/nodejs/test/e2e/rpc_session_state.e2e.test.ts @@ -294,7 +294,7 @@ describe("Session-scoped RPC", async () => { const session = await client.createSession({ onPermissionRequest: approveAll }); const metrics = await session.rpc.usage.getMetrics(); - expect(metrics.sessionStartTime).toBeGreaterThan(0); + expect(Date.parse(metrics.sessionStartTime)).not.toBeNaN(); if (metrics.totalNanoAiu !== undefined && metrics.totalNanoAiu !== null) { expect(metrics.totalNanoAiu).toBeGreaterThanOrEqual(0); } diff --git a/python/copilot/client.py b/python/copilot/client.py index cb5c98c90..3d9f3c781 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -27,6 +27,7 @@ import uuid from collections.abc import Awaitable, Callable from dataclasses import KW_ONLY, dataclass, field +from datetime import datetime, timezone from pathlib import Path from types import TracebackType from typing import Any, Literal, TypedDict, cast, overload @@ -41,6 +42,7 @@ RemoteSessionMode, ServerRpc, _InternalServerRpc, + from_datetime, register_client_session_api_handlers, ) from .generated.session_events import ( @@ -254,7 +256,7 @@ class PingResponse: """Response from ping""" message: str # Echo message with "pong: " prefix - timestamp: int # Server timestamp in milliseconds + timestamp: datetime # ISO 8601 timestamp when the ping was processed protocolVersion: int # Protocol version for SDK compatibility @staticmethod @@ -268,12 +270,17 @@ def from_dict(obj: Any) -> PingResponse: f"Missing required fields in PingResponse: message={message}, " f"timestamp={timestamp}, protocolVersion={protocolVersion}" ) - return PingResponse(str(message), int(timestamp), int(protocolVersion)) + timestamp_value = ( + datetime.fromtimestamp(timestamp / 1000, tz=timezone.utc) + if isinstance(timestamp, (int, float)) + else from_datetime(timestamp) + ) + return PingResponse(str(message), timestamp_value, int(protocolVersion)) def to_dict(self) -> dict: result: dict = {} result["message"] = self.message - result["timestamp"] = self.timestamp + result["timestamp"] = self.timestamp.isoformat() result["protocolVersion"] = self.protocolVersion return result diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index 2cae80644..f344650cd 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -853,14 +853,14 @@ class AutoModeSwitchRequestedData: "Auto mode switch request notification requiring user approval" request_id: str error_code: str | None = None - retry_after_seconds: timedelta | None = None + retry_after_seconds: int | None = None @staticmethod def from_dict(obj: Any) -> "AutoModeSwitchRequestedData": assert isinstance(obj, dict) request_id = from_str(obj.get("requestId")) error_code = from_union([from_none, from_str], obj.get("errorCode")) - retry_after_seconds = from_union([from_none, from_timedelta], obj.get("retryAfterSeconds")) + retry_after_seconds = from_union([from_none, from_int], obj.get("retryAfterSeconds")) return AutoModeSwitchRequestedData( request_id=request_id, error_code=error_code, @@ -873,7 +873,7 @@ def to_dict(self) -> dict: if self.error_code is not None: result["errorCode"] = from_union([from_none, from_str], self.error_code) if self.retry_after_seconds is not None: - result["retryAfterSeconds"] = from_union([from_none, to_timedelta_int], self.retry_after_seconds) + result["retryAfterSeconds"] = from_union([from_none, to_int], self.retry_after_seconds) return result diff --git a/python/copilot/session_fs_provider.py b/python/copilot/session_fs_provider.py index 1421ffaf4..355724da4 100644 --- a/python/copilot/session_fs_provider.py +++ b/python/copilot/session_fs_provider.py @@ -287,13 +287,11 @@ async def sqlite_query(self, params: Any) -> _GeneratedSqliteQueryResult: rows=[], rows_affected=0, ) - rowid = result.last_insert_rowid - wire_rowid = float(rowid) if rowid is not None else None return _GeneratedSqliteQueryResult( columns=result.columns, rows=result.rows, rows_affected=result.rows_affected, - last_insert_rowid=wire_rowid, + last_insert_rowid=result.last_insert_rowid, ) async def sqlite_exists(self, params: Any) -> SessionFSSqliteExistsResult: diff --git a/python/e2e/test_client_e2e.py b/python/e2e/test_client_e2e.py index 1207d10eb..fc7315a58 100644 --- a/python/e2e/test_client_e2e.py +++ b/python/e2e/test_client_e2e.py @@ -27,7 +27,7 @@ async def test_should_start_and_connect_to_server_using_stdio(self): pong = await client.ping("test message") assert pong.message == "pong: test message" - assert pong.timestamp >= 0 + assert pong.timestamp is not None await client.stop() assert client.get_state() == "disconnected" @@ -44,7 +44,7 @@ async def test_should_start_and_connect_to_server_using_tcp(self): pong = await client.ping("test message") assert pong.message == "pong: test message" - assert pong.timestamp >= 0 + assert pong.timestamp is not None await client.stop() assert client.get_state() == "disconnected" diff --git a/python/e2e/test_rpc_e2e.py b/python/e2e/test_rpc_e2e.py index 50dfecc3b..511b9d1d1 100644 --- a/python/e2e/test_rpc_e2e.py +++ b/python/e2e/test_rpc_e2e.py @@ -23,7 +23,7 @@ async def test_should_call_rpc_ping_with_typed_params(self): result = await client.rpc.ping(PingRequest(message="typed rpc test")) assert result.message == "pong: typed rpc test" - assert isinstance(result.timestamp, (int, float)) + assert result.timestamp is not None await client.stop() finally: diff --git a/python/e2e/test_rpc_server_e2e.py b/python/e2e/test_rpc_server_e2e.py index 67efbe733..ce293086b 100644 --- a/python/e2e/test_rpc_server_e2e.py +++ b/python/e2e/test_rpc_server_e2e.py @@ -89,7 +89,7 @@ async def test_should_call_rpc_ping_with_typed_params_and_result(self, ctx: E2ET await ctx.client.start() result = await ctx.client.rpc.ping(PingRequest(message="typed rpc test")) assert result.message == "pong: typed rpc test" - assert result.timestamp >= 0 + assert result.timestamp is not None async def test_should_call_rpc_models_list_with_typed_result(self, authed_ctx: E2ETestContext): token = "rpc-models-token" diff --git a/python/e2e/test_rpc_session_state_e2e.py b/python/e2e/test_rpc_session_state_e2e.py index cba7e2164..b7329158c 100644 --- a/python/e2e/test_rpc_session_state_e2e.py +++ b/python/e2e/test_rpc_session_state_e2e.py @@ -253,7 +253,7 @@ async def test_should_call_session_usage_and_permission_rpcs(self, ctx: E2ETestC ) try: metrics = await session.rpc.usage.get_metrics() - assert metrics.session_start_time > 0 + assert metrics.session_start_time is not None if metrics.total_nano_aiu is not None: assert metrics.total_nano_aiu >= 0 if metrics.token_details is not None: diff --git a/rust/src/generated/api_types.rs b/rust/src/generated/api_types.rs index 7a6d4276b..d58f46df2 100644 --- a/rust/src/generated/api_types.rs +++ b/rust/src/generated/api_types.rs @@ -10,8 +10,7 @@ use super::session_events::{ AbortReason, McpServerSource, McpServerStatus, PermissionPromptRequest, PermissionRule, ReasoningSummary, SessionMode, ShutdownType, SkillSource, UserToolSessionApproval, }; -use crate::types::SessionEvent; -use crate::types::{RequestId, SessionId}; +use crate::types::{RequestId, SessionEvent, SessionId}; /// JSON-RPC method name constants. pub mod rpc_methods { diff --git a/rust/src/types.rs b/rust/src/types.rs index cadf46271..bd1fb6928 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -2346,9 +2346,9 @@ pub struct PingResponse { /// The message echoed back by the CLI. #[serde(default)] pub message: String, - /// Server-side timestamp (Unix epoch milliseconds). + /// ISO 8601 timestamp when the ping was processed. #[serde(default)] - pub timestamp: i64, + pub timestamp: String, /// The protocol version negotiated by the CLI, if reported. #[serde(skip_serializing_if = "Option::is_none")] pub protocol_version: Option, diff --git a/rust/tests/e2e/client.rs b/rust/tests/e2e/client.rs index 34e38a9c0..2003be4b8 100644 --- a/rust/tests/e2e/client.rs +++ b/rust/tests/e2e/client.rs @@ -17,7 +17,7 @@ async fn should_start_ping_and_stop_stdio_client() { let response = client.ping(Some("hello from rust")).await.expect("ping"); assert_eq!(response.message, "pong: hello from rust"); - assert!(response.timestamp > 0); + assert!(!response.timestamp.is_empty()); client.stop().await.expect("stop client"); assert_eq!(client.state(), ConnectionState::Disconnected); diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts index e65ec0054..52b11ed59 100644 --- a/scripts/codegen/python.ts +++ b/scripts/codegen/python.ts @@ -654,6 +654,10 @@ function stripDurationMillisecondsSuffix(name: string): string { return name; } +function isSecondsDurationPropertyName(propName: string | undefined): boolean { + return propName !== undefined && /seconds$/i.test(propName); +} + function isPyDurationProperty(propSchema: JSONSchema7, ctx: PyCodegenCtx): boolean { if (propSchema.$ref && typeof propSchema.$ref === "string") { const resolved = resolveSchema(propSchema, ctx.definitions); @@ -1371,7 +1375,7 @@ function resolvePyPropertyType( } if (type === "integer") { - if (format === "duration") { + if (format === "duration" && !isSecondsDurationPropertyName(jsonPropName)) { const resolved = pyDurationResolvedType(ctx, true); return isRequired ? resolved : pyOptionalResolvedType(resolved); } @@ -1380,7 +1384,7 @@ function resolvePyPropertyType( } if (type === "number") { - if (format === "duration") { + if (format === "duration" && !isSecondsDurationPropertyName(jsonPropName)) { const resolved = pyDurationResolvedType(ctx, false); return isRequired ? resolved : pyOptionalResolvedType(resolved); } diff --git a/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml b/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml index abe4a4f5a..b5196952a 100644 --- a/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml +++ b/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml @@ -42,6 +42,6 @@ conversations: content: Tool 'view' does not exist. Available tools that can be called are report_intent. - role: tool tool_call_id: toolcall_0 - content: Intent logged + content: modified by post hook - role: assistant content: Done. From 5946de68931b6bf3afde3c53ee848fc865f0f190 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Wed, 20 May 2026 00:09:05 -0400 Subject: [PATCH 5/6] Fix post-tool hook snapshot parity Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs | 7 ++++++- go/internal/e2e/hooks_extended_e2e_test.go | 6 +++++- python/copilot/client.py | 4 ++-- python/e2e/test_hooks_extended_e2e.py | 6 +++++- rust/tests/e2e/hooks_extended.rs | 6 +++++- .../should_allow_posttooluse_to_return_modifiedresult.yaml | 6 +++--- 6 files changed, 26 insertions(+), 9 deletions(-) diff --git a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs index d1e483779..6bb589391 100644 --- a/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs +++ b/dotnet/test/E2E/HookLifecycleAndOutputE2ETests.cs @@ -322,7 +322,12 @@ public async Task Should_Allow_PostToolUse_To_Return_ModifiedResult() return Task.FromResult(new PostToolUseHookOutput { - ModifiedResult = "modified by post hook", + ModifiedResult = new ToolResultObject + { + TextResultForLlm = "modified by post hook", + ResultType = "success", + ToolTelemetry = new Dictionary(), + }, SuppressOutput = false, }); }, diff --git a/go/internal/e2e/hooks_extended_e2e_test.go b/go/internal/e2e/hooks_extended_e2e_test.go index 5ef8eabc9..bc0144eaf 100644 --- a/go/internal/e2e/hooks_extended_e2e_test.go +++ b/go/internal/e2e/hooks_extended_e2e_test.go @@ -301,7 +301,11 @@ func TestHooksExtendedE2E(t *testing.T) { return nil, nil } return &copilot.PostToolUseHookOutput{ - ModifiedResult: "modified by post hook", + ModifiedResult: copilot.ToolResult{ + TextResultForLLM: "modified by post hook", + ResultType: "success", + ToolTelemetry: map[string]any{}, + }, SuppressOutput: false, }, nil }, diff --git a/python/copilot/client.py b/python/copilot/client.py index 3d9f3c781..6adb52061 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -27,7 +27,7 @@ import uuid from collections.abc import Awaitable, Callable from dataclasses import KW_ONLY, dataclass, field -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path from types import TracebackType from typing import Any, Literal, TypedDict, cast, overload @@ -271,7 +271,7 @@ def from_dict(obj: Any) -> PingResponse: f"timestamp={timestamp}, protocolVersion={protocolVersion}" ) timestamp_value = ( - datetime.fromtimestamp(timestamp / 1000, tz=timezone.utc) + datetime.fromtimestamp(timestamp / 1000, tz=UTC) if isinstance(timestamp, (int, float)) else from_datetime(timestamp) ) diff --git a/python/e2e/test_hooks_extended_e2e.py b/python/e2e/test_hooks_extended_e2e.py index 6f87a438f..fe6a0ea2a 100644 --- a/python/e2e/test_hooks_extended_e2e.py +++ b/python/e2e/test_hooks_extended_e2e.py @@ -163,7 +163,11 @@ async def on_post_tool_use(input_data, invocation): if input_data.get("toolName") != "report_intent": return None return { - "modifiedResult": "modified by post hook", + "modifiedResult": { + "textResultForLlm": "modified by post hook", + "resultType": "success", + "toolTelemetry": {}, + }, "suppressOutput": False, } diff --git a/rust/tests/e2e/hooks_extended.rs b/rust/tests/e2e/hooks_extended.rs index 3b11ddee1..632a7b83a 100644 --- a/rust/tests/e2e/hooks_extended.rs +++ b/rust/tests/e2e/hooks_extended.rs @@ -523,7 +523,11 @@ impl SessionHooks for RecordingHooks { _ctx: HookContext, ) -> Option { let output = (input.tool_name == "report_intent").then(|| PostToolUseOutput { - modified_result: Some(json!("modified by post hook")), + modified_result: Some(json!({ + "textResultForLlm": "modified by post hook", + "resultType": "success", + "toolTelemetry": {}, + })), suppress_output: Some(false), ..PostToolUseOutput::default() }); diff --git a/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml b/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml index b5196952a..cf1292873 100644 --- a/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml +++ b/test/snapshots/hooks_extended/should_allow_posttooluse_to_return_modifiedresult.yaml @@ -37,11 +37,11 @@ conversations: function: name: view arguments: '{"path":"${workdir}"}' - - role: tool - tool_call_id: toolcall_1 - content: Tool 'view' does not exist. Available tools that can be called are report_intent. - role: tool tool_call_id: toolcall_0 content: modified by post hook + - role: tool + tool_call_id: toolcall_1 + content: Tool 'view' does not exist. Available tools that can be called are report_intent. - role: assistant content: Done. From 97f9d8e2e1dbf9bd213bd3327e6d3bfa18c8e752 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Wed, 20 May 2026 00:24:31 -0400 Subject: [PATCH 6/6] Fix Rust hook e2e test isolation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- rust/tests/e2e/hooks_extended.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/rust/tests/e2e/hooks_extended.rs b/rust/tests/e2e/hooks_extended.rs index 632a7b83a..e73b82aa5 100644 --- a/rust/tests/e2e/hooks_extended.rs +++ b/rust/tests/e2e/hooks_extended.rs @@ -522,14 +522,16 @@ impl SessionHooks for RecordingHooks { input: PostToolUseInput, _ctx: HookContext, ) -> Option { - let output = (input.tool_name == "report_intent").then(|| PostToolUseOutput { - modified_result: Some(json!({ - "textResultForLlm": "modified by post hook", - "resultType": "success", - "toolTelemetry": {}, - })), - suppress_output: Some(false), - ..PostToolUseOutput::default() + let output = (self.post_tool.is_some() && input.tool_name == "report_intent").then(|| { + PostToolUseOutput { + modified_result: Some(json!({ + "textResultForLlm": "modified by post hook", + "resultType": "success", + "toolTelemetry": {}, + })), + suppress_output: Some(false), + ..PostToolUseOutput::default() + } }); if let Some(tx) = &self.post_tool { let _ = tx.send(input);