diff --git a/dotnet/src/Generated/Rpc.cs b/dotnet/src/Generated/Rpc.cs
index 295fb8bfa..0c9880de6 100644
--- a/dotnet/src/Generated/Rpc.cs
+++ b/dotnet/src/Generated/Rpc.cs
@@ -815,6 +815,58 @@ internal sealed class WorkspacesCreateFileRequest
public string Content { get; set; } = string.Empty;
}
+/// RPC data type for InstructionsSources operations.
+public sealed class InstructionsSources
+{
+ /// Unique identifier for this source (used for toggling).
+ [JsonPropertyName("id")]
+ public string Id { get; set; } = string.Empty;
+
+ /// Human-readable label.
+ [JsonPropertyName("label")]
+ public string Label { get; set; } = string.Empty;
+
+ /// File path relative to repo or absolute for home.
+ [JsonPropertyName("sourcePath")]
+ public string SourcePath { get; set; } = string.Empty;
+
+ /// Raw content of the instruction file.
+ [JsonPropertyName("content")]
+ public string Content { get; set; } = string.Empty;
+
+ /// Category of instruction source — used for merge logic.
+ [JsonPropertyName("type")]
+ public InstructionsSourcesType Type { get; set; }
+
+ /// Where this source lives — used for UI grouping.
+ [JsonPropertyName("location")]
+ public InstructionsSourcesLocation Location { get; set; }
+
+ /// Glob pattern from frontmatter — when set, this instruction applies only to matching files.
+ [JsonPropertyName("applyTo")]
+ public string? ApplyTo { get; set; }
+
+ /// Short description (body after frontmatter) for use in instruction tables.
+ [JsonPropertyName("description")]
+ public string? Description { get; set; }
+}
+
+/// RPC data type for InstructionsGetSources operations.
+public sealed class InstructionsGetSourcesResult
+{
+ /// Instruction sources for the session.
+ [JsonPropertyName("sources")]
+ public IList Sources { get => field ??= []; set; }
+}
+
+/// RPC data type for SessionInstructionsGetSources operations.
+internal sealed class SessionInstructionsGetSourcesRequest
+{
+ /// Target session identifier.
+ [JsonPropertyName("sessionId")]
+ public string SessionId { get; set; } = string.Empty;
+}
+
/// RPC data type for FleetStart operations.
[Experimental(Diagnostics.Experimental)]
public sealed class FleetStartResult
@@ -837,8 +889,8 @@ internal sealed class FleetStartRequest
public string? Prompt { get; set; }
}
-/// RPC data type for Agent operations.
-public sealed class Agent
+/// RPC data type for AgentInfo operations.
+public sealed class AgentInfo
{
/// Unique identifier of the custom agent.
[JsonPropertyName("name")]
@@ -859,7 +911,7 @@ public sealed class AgentList
{
/// Available custom agents.
[JsonPropertyName("agents")]
- public IList Agents { get => field ??= []; set; }
+ public IList Agents { get => field ??= []; set; }
}
/// RPC data type for SessionAgentList operations.
@@ -871,29 +923,13 @@ internal sealed class SessionAgentListRequest
public string SessionId { get; set; } = string.Empty;
}
-/// RPC data type for AgentGetCurrentResultAgent operations.
-public sealed class AgentGetCurrentResultAgent
-{
- /// Unique identifier of the custom agent.
- [JsonPropertyName("name")]
- public string Name { get; set; } = string.Empty;
-
- /// Human-readable display name.
- [JsonPropertyName("displayName")]
- public string DisplayName { get; set; } = string.Empty;
-
- /// Description of the agent's purpose.
- [JsonPropertyName("description")]
- public string Description { get; set; } = string.Empty;
-}
-
/// RPC data type for AgentGetCurrent operations.
[Experimental(Diagnostics.Experimental)]
public sealed class AgentGetCurrentResult
{
/// Currently selected custom agent, or null if using the default agent.
[JsonPropertyName("agent")]
- public AgentGetCurrentResultAgent? Agent { get; set; }
+ public AgentInfo? Agent { get; set; }
}
/// RPC data type for SessionAgentGetCurrent operations.
@@ -905,29 +941,13 @@ internal sealed class SessionAgentGetCurrentRequest
public string SessionId { get; set; } = string.Empty;
}
-/// The newly selected custom agent.
-public sealed class AgentSelectAgent
-{
- /// Unique identifier of the custom agent.
- [JsonPropertyName("name")]
- public string Name { get; set; } = string.Empty;
-
- /// Human-readable display name.
- [JsonPropertyName("displayName")]
- public string DisplayName { get; set; } = string.Empty;
-
- /// Description of the agent's purpose.
- [JsonPropertyName("description")]
- public string Description { get; set; } = string.Empty;
-}
-
/// RPC data type for AgentSelect operations.
[Experimental(Diagnostics.Experimental)]
public sealed class AgentSelectResult
{
/// The newly selected custom agent.
[JsonPropertyName("agent")]
- public AgentSelectAgent Agent { get => field ??= new(); set; }
+ public AgentInfo Agent { get => field ??= new(); set; }
}
/// RPC data type for AgentSelect operations.
@@ -952,29 +972,13 @@ internal sealed class SessionAgentDeselectRequest
public string SessionId { get; set; } = string.Empty;
}
-/// RPC data type for AgentReloadAgent operations.
-public sealed class AgentReloadAgent
-{
- /// Unique identifier of the custom agent.
- [JsonPropertyName("name")]
- public string Name { get; set; } = string.Empty;
-
- /// Human-readable display name.
- [JsonPropertyName("displayName")]
- public string DisplayName { get; set; } = string.Empty;
-
- /// Description of the agent's purpose.
- [JsonPropertyName("description")]
- public string Description { get; set; } = string.Empty;
-}
-
/// RPC data type for AgentReload operations.
[Experimental(Diagnostics.Experimental)]
public sealed class AgentReloadResult
{
/// Reloaded custom agents.
[JsonPropertyName("agents")]
- public IList Agents { get => field ??= []; set; }
+ public IList Agents { get => field ??= []; set; }
}
/// RPC data type for SessionAgentReload operations.
@@ -2009,6 +2013,47 @@ public enum WorkspacesGetWorkspaceResultWorkspaceSessionSyncLevel
}
+/// Category of instruction source — used for merge logic.
+[JsonConverter(typeof(JsonStringEnumConverter))]
+public enum InstructionsSourcesType
+{
+ /// The home variant.
+ [JsonStringEnumMemberName("home")]
+ Home,
+ /// The repo variant.
+ [JsonStringEnumMemberName("repo")]
+ Repo,
+ /// The model variant.
+ [JsonStringEnumMemberName("model")]
+ Model,
+ /// The vscode variant.
+ [JsonStringEnumMemberName("vscode")]
+ Vscode,
+ /// The nested-agents variant.
+ [JsonStringEnumMemberName("nested-agents")]
+ NestedAgents,
+ /// The child-instructions variant.
+ [JsonStringEnumMemberName("child-instructions")]
+ ChildInstructions,
+}
+
+
+/// Where this source lives — used for UI grouping.
+[JsonConverter(typeof(JsonStringEnumConverter))]
+public enum InstructionsSourcesLocation
+{
+ /// The user variant.
+ [JsonStringEnumMemberName("user")]
+ User,
+ /// The repository variant.
+ [JsonStringEnumMemberName("repository")]
+ Repository,
+ /// The working-directory variant.
+ [JsonStringEnumMemberName("working-directory")]
+ WorkingDirectory,
+}
+
+
/// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum McpServerStatus
@@ -2380,6 +2425,7 @@ internal SessionRpc(JsonRpc rpc, string sessionId)
Name = new NameApi(rpc, sessionId);
Plan = new PlanApi(rpc, sessionId);
Workspaces = new WorkspacesApi(rpc, sessionId);
+ Instructions = new InstructionsApi(rpc, sessionId);
Fleet = new FleetApi(rpc, sessionId);
Agent = new AgentApi(rpc, sessionId);
Skills = new SkillsApi(rpc, sessionId);
@@ -2410,6 +2456,9 @@ internal SessionRpc(JsonRpc rpc, string sessionId)
/// Workspaces APIs.
public WorkspacesApi Workspaces { get; }
+ /// Instructions APIs.
+ public InstructionsApi Instructions { get; }
+
/// Fleet APIs.
public FleetApi Fleet { get; }
@@ -2613,6 +2662,26 @@ public async Task CreateFileAsync(string path, string content, CancellationToken
}
}
+/// Provides session-scoped Instructions APIs.
+public sealed class InstructionsApi
+{
+ private readonly JsonRpc _rpc;
+ private readonly string _sessionId;
+
+ internal InstructionsApi(JsonRpc rpc, string sessionId)
+ {
+ _rpc = rpc;
+ _sessionId = sessionId;
+ }
+
+ /// Calls "session.instructions.getSources".
+ public async Task GetSourcesAsync(CancellationToken cancellationToken = default)
+ {
+ var request = new SessionInstructionsGetSourcesRequest { SessionId = _sessionId };
+ return await CopilotClient.InvokeRpcAsync(_rpc, "session.instructions.getSources", [request], cancellationToken);
+ }
+}
+
/// Provides session-scoped Fleet APIs.
[Experimental(Diagnostics.Experimental)]
public sealed class FleetApi
@@ -3144,13 +3213,10 @@ public static void RegisterClientSessionApiHandlers(JsonRpc rpc, FuncUpdated working directory and git context after the change.
+/// Working directory and git context at session start.
/// Represents the session.context_changed event.
public partial class SessionContextChangedEvent : SessionEvent
{
@@ -731,7 +731,7 @@ public partial class HookEndEvent : SessionEvent
public required HookEndData Data { get; set; }
}
-/// System or developer message content with role and optional template metadata.
+/// System/developer instruction content with role and optional template metadata.
/// Represents the system.message event.
public partial class SystemMessageEvent : SessionEvent
{
@@ -1124,7 +1124,7 @@ public partial class SessionStartData
/// Working directory and git context at session start.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("context")]
- public StartContext? Context { get; set; }
+ public WorkingDirectoryContext? Context { get; set; }
/// Whether the session was already in use by another client at start time.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@@ -1161,7 +1161,7 @@ public partial class SessionResumeData
/// Updated working directory and git context at resume time.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("context")]
- public ResumeContext? Context { get; set; }
+ public WorkingDirectoryContext? Context { get; set; }
/// Whether the session was already in use by another client at resume time.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@@ -1469,7 +1469,7 @@ public partial class SessionShutdownData
public double? ToolDefinitionsTokens { get; set; }
}
-/// Updated working directory and git context after the change.
+/// Working directory and git context at session start.
public partial class SessionContextChangedData
{
/// Current working directory path.
@@ -1489,7 +1489,7 @@ public partial class SessionContextChangedData
/// Hosting platform type of the repository (github or ado).
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("hostType")]
- public ContextChangedHostType? HostType { get; set; }
+ public WorkingDirectoryContextHostType? HostType { get; set; }
/// Current git branch name.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@@ -1671,6 +1671,16 @@ public partial class UserMessageData
[JsonPropertyName("attachments")]
public UserMessageAttachment[]? Attachments { get; set; }
+ /// Normalized document MIME types that were sent natively instead of through tagged_files XML.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("supportedNativeDocumentMimeTypes")]
+ public string[]? SupportedNativeDocumentMimeTypes { get; set; }
+
+ /// Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit.
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [JsonPropertyName("nativeDocumentPathFallbackPaths")]
+ public string[]? NativeDocumentPathFallbackPaths { get; set; }
+
/// Origin of this message, used for timeline filtering (e.g., "skill-pdf" for skill-injected messages that should be hidden from the user).
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("source")]
@@ -1797,6 +1807,7 @@ public partial class AssistantMessageData
public string? RequestId { get; set; }
/// Tool call ID of the parent tool invocation when this event originates from a sub-agent.
+ [Obsolete("This member is deprecated and will be removed in a future version.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -1814,6 +1825,7 @@ public partial class AssistantMessageDeltaData
public required string DeltaContent { get; set; }
/// Tool call ID of the parent tool invocation when this event originates from a sub-agent.
+ [Obsolete("This member is deprecated and will be removed in a future version.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -1895,6 +1907,7 @@ public partial class AssistantUsageData
public string? ProviderCallId { get; set; }
/// Parent tool call ID when this usage originates from a sub-agent.
+ [Obsolete("This member is deprecated and will be removed in a future version.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -1967,6 +1980,7 @@ public partial class ToolExecutionStartData
public string? McpToolName { get; set; }
/// Tool call ID of the parent tool invocation when this event originates from a sub-agent.
+ [Obsolete("This member is deprecated and will be removed in a future version.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -2038,6 +2052,7 @@ public partial class ToolExecutionCompleteData
public IDictionary? ToolTelemetry { get; set; }
/// Tool call ID of the parent tool invocation when this event originates from a sub-agent.
+ [Obsolete("This member is deprecated and will be removed in a future version.")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("parentToolCallId")]
public string? ParentToolCallId { get; set; }
@@ -2239,10 +2254,10 @@ public partial class HookEndData
public HookEndError? Error { get; set; }
}
-/// System or developer message content with role and optional template metadata.
+/// System/developer instruction content with role and optional template metadata.
public partial class SystemMessageData
{
- /// The system or developer prompt text.
+ /// The system or developer prompt text sent as model input.
[JsonPropertyName("content")]
public required string Content { get; set; }
@@ -2673,8 +2688,8 @@ public partial class SessionExtensionsLoadedData
}
/// Working directory and git context at session start.
-/// Nested data type for StartContext.
-public partial class StartContext
+/// Nested data type for WorkingDirectoryContext.
+public partial class WorkingDirectoryContext
{
/// Current working directory path.
[JsonPropertyName("cwd")]
@@ -2693,46 +2708,7 @@ public partial class StartContext
/// Hosting platform type of the repository (github or ado).
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("hostType")]
- public StartContextHostType? HostType { get; set; }
-
- /// Current git branch name.
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("branch")]
- public string? Branch { get; set; }
-
- /// Head commit of current git branch at session start time.
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("headCommit")]
- public string? HeadCommit { get; set; }
-
- /// Base commit of current git branch at session start time.
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("baseCommit")]
- public string? BaseCommit { get; set; }
-}
-
-/// Updated working directory and git context at resume time.
-/// Nested data type for ResumeContext.
-public partial class ResumeContext
-{
- /// Current working directory path.
- [JsonPropertyName("cwd")]
- public required string Cwd { get; set; }
-
- /// Root directory of the git repository, resolved via git rev-parse.
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("gitRoot")]
- public string? GitRoot { get; set; }
-
- /// Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps).
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("repository")]
- public string? Repository { get; set; }
-
- /// Hosting platform type of the repository (github or ado).
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
- [JsonPropertyName("hostType")]
- public ResumeContextHostType? HostType { get; set; }
+ public WorkingDirectoryContextHostType? HostType { get; set; }
/// Current git branch name.
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
@@ -3872,20 +3848,8 @@ public partial class ExtensionsLoadedExtension
}
/// Hosting platform type of the repository (github or ado).
-[JsonConverter(typeof(JsonStringEnumConverter))]
-public enum StartContextHostType
-{
- /// The github variant.
- [JsonStringEnumMemberName("github")]
- Github,
- /// The ado variant.
- [JsonStringEnumMemberName("ado")]
- Ado,
-}
-
-/// Hosting platform type of the repository (github or ado).
-[JsonConverter(typeof(JsonStringEnumConverter))]
-public enum ResumeContextHostType
+[JsonConverter(typeof(JsonStringEnumConverter))]
+public enum WorkingDirectoryContextHostType
{
/// The github variant.
[JsonStringEnumMemberName("github")]
@@ -3946,18 +3910,6 @@ public enum ShutdownType
Error,
}
-/// Hosting platform type of the repository (github or ado).
-[JsonConverter(typeof(JsonStringEnumConverter))]
-public enum ContextChangedHostType
-{
- /// The github variant.
- [JsonStringEnumMemberName("github")]
- Github,
- /// The ado variant.
- [JsonStringEnumMemberName("ado")]
- Ado,
-}
-
/// Type of GitHub reference.
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum UserMessageAttachmentGithubReferenceType
@@ -4278,7 +4230,6 @@ public enum ExtensionsLoadedExtensionStatus
[JsonSerializable(typeof(PermissionRequestWrite))]
[JsonSerializable(typeof(PermissionRequestedData))]
[JsonSerializable(typeof(PermissionRequestedEvent))]
-[JsonSerializable(typeof(ResumeContext))]
[JsonSerializable(typeof(SamplingCompletedData))]
[JsonSerializable(typeof(SamplingCompletedEvent))]
[JsonSerializable(typeof(SamplingRequestedData))]
@@ -4344,7 +4295,6 @@ public enum ExtensionsLoadedExtensionStatus
[JsonSerializable(typeof(SkillInvokedData))]
[JsonSerializable(typeof(SkillInvokedEvent))]
[JsonSerializable(typeof(SkillsLoadedSkill))]
-[JsonSerializable(typeof(StartContext))]
[JsonSerializable(typeof(SubagentCompletedData))]
[JsonSerializable(typeof(SubagentCompletedEvent))]
[JsonSerializable(typeof(SubagentDeselectedData))]
@@ -4401,5 +4351,6 @@ public enum ExtensionsLoadedExtensionStatus
[JsonSerializable(typeof(UserMessageAttachmentSelectionDetailsStart))]
[JsonSerializable(typeof(UserMessageData))]
[JsonSerializable(typeof(UserMessageEvent))]
+[JsonSerializable(typeof(WorkingDirectoryContext))]
[JsonSerializable(typeof(JsonElement))]
internal partial class SessionEventsJsonContext : JsonSerializerContext;
\ No newline at end of file
diff --git a/go/generated_session_events.go b/go/generated_session_events.go
index 01a6a0811..95ace9123 100644
--- a/go/generated_session_events.go
+++ b/go/generated_session_events.go
@@ -637,7 +637,7 @@ type SessionStartData struct {
// Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh")
ReasoningEffort *string `json:"reasoningEffort,omitempty"`
// Working directory and git context at session start
- Context *StartContext `json:"context,omitempty"`
+ Context *WorkingDirectoryContext `json:"context,omitempty"`
// Whether the session was already in use by another client at start time
AlreadyInUse *bool `json:"alreadyInUse,omitempty"`
// Whether this session supports remote steering via Mission Control
@@ -657,7 +657,7 @@ type SessionResumeData struct {
// Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh")
ReasoningEffort *string `json:"reasoningEffort,omitempty"`
// Updated working directory and git context at resume time
- Context *ResumeContext `json:"context,omitempty"`
+ Context *WorkingDirectoryContext `json:"context,omitempty"`
// Whether the session was already in use by another client at resume time
AlreadyInUse *bool `json:"alreadyInUse,omitempty"`
// Whether this session supports remote steering via Mission Control
@@ -856,7 +856,7 @@ type SessionShutdownData struct {
func (*SessionShutdownData) sessionEventData() {}
-// Updated working directory and git context after the change
+// Working directory and git context at session start
type SessionContextChangedData struct {
// Current working directory path
Cwd string `json:"cwd"`
@@ -865,7 +865,7 @@ type SessionContextChangedData struct {
// Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
Repository *string `json:"repository,omitempty"`
// Hosting platform type of the repository (github or ado)
- HostType *ContextChangedHostType `json:"hostType,omitempty"`
+ HostType *WorkingDirectoryContextHostType `json:"hostType,omitempty"`
// Current git branch name
Branch *string `json:"branch,omitempty"`
// Head commit of current git branch at session start time
@@ -962,6 +962,10 @@ type UserMessageData struct {
TransformedContent *string `json:"transformedContent,omitempty"`
// Files, selections, or GitHub references attached to the message
Attachments []UserMessageAttachment `json:"attachments,omitempty"`
+ // Normalized document MIME types that were sent natively instead of through tagged_files XML
+ SupportedNativeDocumentMIMETypes []string `json:"supportedNativeDocumentMimeTypes,omitempty"`
+ // Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit
+ NativeDocumentPathFallbackPaths []string `json:"nativeDocumentPathFallbackPaths,omitempty"`
// Origin of this message, used for timeline filtering (e.g., "skill-pdf" for skill-injected messages that should be hidden from the user)
Source *string `json:"source,omitempty"`
// The agent mode that was active when this message was sent
@@ -1047,6 +1051,7 @@ type AssistantMessageData struct {
// GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs
RequestID *string `json:"requestId,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"`
}
@@ -1059,6 +1064,7 @@ type AssistantMessageDeltaData struct {
// Incremental text chunk to append to the message content
DeltaContent string `json:"deltaContent"`
// 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"`
}
@@ -1101,6 +1107,7 @@ type AssistantUsageData struct {
// GitHub request tracing ID (x-github-request-id header) for server-side log correlation
ProviderCallID *string `json:"providerCallId,omitempty"`
// Parent tool call ID when this usage originates from a sub-agent
+ // Deprecated: ParentToolCallID is deprecated.
ParentToolCallID *string `json:"parentToolCallId,omitempty"`
// Per-quota resource usage snapshots, keyed by quota identifier
QuotaSnapshots map[string]AssistantUsageQuotaSnapshot `json:"quotaSnapshots,omitempty"`
@@ -1145,6 +1152,7 @@ type ToolExecutionStartData struct {
// Original tool name on the MCP server, when the tool is an MCP tool
McpToolName *string `json:"mcpToolName,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"`
}
@@ -1189,6 +1197,7 @@ type ToolExecutionCompleteData struct {
// Tool-specific telemetry data (e.g., CodeQL check counts, grep match counts)
ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"`
// Tool call ID of the parent tool invocation when this event originates from a sub-agent
+ // Deprecated: ParentToolCallID is deprecated.
ParentToolCallID *string `json:"parentToolCallId,omitempty"`
}
@@ -1316,9 +1325,9 @@ type HookEndData struct {
func (*HookEndData) sessionEventData() {}
-// System or developer message content with role and optional template metadata
+// System/developer instruction content with role and optional template metadata
type SystemMessageData struct {
- // The system or developer prompt text
+ // The system or developer prompt text sent as model input
Content string `json:"content"`
// Message role: "system" for system prompts, "developer" for developer-injected instructions
Role SystemMessageRole `json:"role"`
@@ -1632,25 +1641,7 @@ type SessionExtensionsLoadedData struct {
func (*SessionExtensionsLoadedData) sessionEventData() {}
// Working directory and git context at session start
-type StartContext struct {
- // Current working directory path
- Cwd string `json:"cwd"`
- // Root directory of the git repository, resolved via git rev-parse
- GitRoot *string `json:"gitRoot,omitempty"`
- // Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
- Repository *string `json:"repository,omitempty"`
- // Hosting platform type of the repository (github or ado)
- HostType *StartContextHostType `json:"hostType,omitempty"`
- // Current git branch name
- Branch *string `json:"branch,omitempty"`
- // Head commit of current git branch at session start time
- HeadCommit *string `json:"headCommit,omitempty"`
- // Base commit of current git branch at session start time
- BaseCommit *string `json:"baseCommit,omitempty"`
-}
-
-// Updated working directory and git context at resume time
-type ResumeContext struct {
+type WorkingDirectoryContext struct {
// Current working directory path
Cwd string `json:"cwd"`
// Root directory of the git repository, resolved via git rev-parse
@@ -1658,7 +1649,7 @@ type ResumeContext struct {
// Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
Repository *string `json:"repository,omitempty"`
// Hosting platform type of the repository (github or ado)
- HostType *ResumeContextHostType `json:"hostType,omitempty"`
+ HostType *WorkingDirectoryContextHostType `json:"hostType,omitempty"`
// Current git branch name
Branch *string `json:"branch,omitempty"`
// Head commit of current git branch at session start time
@@ -2109,19 +2100,11 @@ type ExtensionsLoadedExtension struct {
}
// Hosting platform type of the repository (github or ado)
-type StartContextHostType string
+type WorkingDirectoryContextHostType string
const (
- StartContextHostTypeGithub StartContextHostType = "github"
- StartContextHostTypeAdo StartContextHostType = "ado"
-)
-
-// Hosting platform type of the repository (github or ado)
-type ResumeContextHostType string
-
-const (
- ResumeContextHostTypeGithub ResumeContextHostType = "github"
- ResumeContextHostTypeAdo ResumeContextHostType = "ado"
+ WorkingDirectoryContextHostTypeGithub WorkingDirectoryContextHostType = "github"
+ WorkingDirectoryContextHostTypeAdo WorkingDirectoryContextHostType = "ado"
)
// The type of operation performed on the plan file
@@ -2157,14 +2140,6 @@ const (
ShutdownTypeError ShutdownType = "error"
)
-// Hosting platform type of the repository (github or ado)
-type ContextChangedHostType string
-
-const (
- ContextChangedHostTypeGithub ContextChangedHostType = "github"
- ContextChangedHostTypeAdo ContextChangedHostType = "ado"
-)
-
// Type discriminator for UserMessageAttachment.
type UserMessageAttachmentType string
diff --git a/go/internal/e2e/multi_client_test.go b/go/internal/e2e/multi_client_test.go
index 389912284..3b009e898 100644
--- a/go/internal/e2e/multi_client_test.go
+++ b/go/internal/e2e/multi_client_test.go
@@ -200,9 +200,7 @@ func TestMultiClient(t *testing.T) {
mu1.Lock()
c1PermRequested := filterEventsByType(client1Events, copilot.SessionEventTypePermissionRequested)
mu1.Unlock()
- mu2.Lock()
- c2PermRequested := filterEventsByType(client2Events, copilot.SessionEventTypePermissionRequested)
- mu2.Unlock()
+ c2PermRequested := waitForEventsByType(t, &mu2, &client2Events, copilot.SessionEventTypePermissionRequested, 5*time.Second)
if len(c1PermRequested) == 0 {
t.Errorf("Expected client 1 to see permission.requested events")
@@ -215,9 +213,7 @@ func TestMultiClient(t *testing.T) {
mu1.Lock()
c1PermCompleted := filterEventsByType(client1Events, copilot.SessionEventTypePermissionCompleted)
mu1.Unlock()
- mu2.Lock()
- c2PermCompleted := filterEventsByType(client2Events, copilot.SessionEventTypePermissionCompleted)
- mu2.Unlock()
+ c2PermCompleted := waitForEventsByType(t, &mu2, &client2Events, copilot.SessionEventTypePermissionCompleted, 5*time.Second)
if len(c1PermCompleted) == 0 {
t.Errorf("Expected client 1 to see permission.completed events")
@@ -297,9 +293,7 @@ func TestMultiClient(t *testing.T) {
mu1.Lock()
c1PermRequested := filterEventsByType(client1Events, copilot.SessionEventTypePermissionRequested)
mu1.Unlock()
- mu2.Lock()
- c2PermRequested := filterEventsByType(client2Events, copilot.SessionEventTypePermissionRequested)
- mu2.Unlock()
+ c2PermRequested := waitForEventsByType(t, &mu2, &client2Events, copilot.SessionEventTypePermissionRequested, 5*time.Second)
if len(c1PermRequested) == 0 {
t.Errorf("Expected client 1 to see permission.requested events")
@@ -312,9 +306,7 @@ func TestMultiClient(t *testing.T) {
mu1.Lock()
c1PermCompleted := filterEventsByType(client1Events, copilot.SessionEventTypePermissionCompleted)
mu1.Unlock()
- mu2.Lock()
- c2PermCompleted := filterEventsByType(client2Events, copilot.SessionEventTypePermissionCompleted)
- mu2.Unlock()
+ c2PermCompleted := waitForEventsByType(t, &mu2, &client2Events, copilot.SessionEventTypePermissionCompleted, 5*time.Second)
if len(c1PermCompleted) == 0 {
t.Errorf("Expected client 1 to see permission.completed events")
@@ -519,3 +511,20 @@ func filterEventsByType(events []copilot.SessionEvent, eventType copilot.Session
}
return filtered
}
+
+// waitForEventsByType polls the event slice until at least one event of the given type appears
+// or the timeout is reached. This avoids flaky assertions on async event delivery.
+func waitForEventsByType(t *testing.T, mu *sync.Mutex, events *[]copilot.SessionEvent, eventType copilot.SessionEventType, timeout time.Duration) []copilot.SessionEvent {
+ t.Helper()
+ deadline := time.Now().Add(timeout)
+ for time.Now().Before(deadline) {
+ mu.Lock()
+ filtered := filterEventsByType(*events, eventType)
+ mu.Unlock()
+ if len(filtered) > 0 {
+ return filtered
+ }
+ time.Sleep(50 * time.Millisecond)
+ }
+ return nil
+}
diff --git a/go/rpc/generated_rpc.go b/go/rpc/generated_rpc.go
index 23bdfb618..528a933b5 100644
--- a/go/rpc/generated_rpc.go
+++ b/go/rpc/generated_rpc.go
@@ -12,6 +12,319 @@ import (
"time"
)
+type UIElicitationResponseContent map[string]*UIElicitationFieldValue
+
+// Model capabilities and limits
+type ModelCapabilities struct {
+ // Token limits for prompts, outputs, and context window
+ Limits *ModelCapabilitiesLimits `json:"limits,omitempty"`
+ // Feature flags indicating what the model supports
+ Supports *ModelCapabilitiesSupports `json:"supports,omitempty"`
+}
+
+// Token limits for prompts, outputs, and context window
+type ModelCapabilitiesLimits struct {
+ // Maximum total context window size in tokens
+ MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"`
+ // Maximum number of output/completion tokens
+ MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
+ // Maximum number of prompt/input tokens
+ MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"`
+ // Vision-specific limits
+ Vision *PurpleModelCapabilitiesLimitsVision `json:"vision,omitempty"`
+}
+
+// Vision-specific limits
+type PurpleModelCapabilitiesLimitsVision struct {
+ // Maximum image size in bytes
+ MaxPromptImageSize int64 `json:"max_prompt_image_size"`
+ // Maximum number of images per prompt
+ MaxPromptImages int64 `json:"max_prompt_images"`
+ // MIME types the model accepts
+ SupportedMediaTypes []string `json:"supported_media_types"`
+}
+
+// Feature flags indicating what the model supports
+type ModelCapabilitiesSupports struct {
+ // Whether this model supports reasoning effort configuration
+ ReasoningEffort *bool `json:"reasoningEffort,omitempty"`
+ // Whether this model supports vision/image input
+ Vision *bool `json:"vision,omitempty"`
+}
+
+// Vision-specific limits
+type ModelCapabilitiesLimitsVision struct {
+ // Maximum image size in bytes
+ MaxPromptImageSize int64 `json:"max_prompt_image_size"`
+ // Maximum number of images per prompt
+ MaxPromptImages int64 `json:"max_prompt_images"`
+ // MIME types the model accepts
+ SupportedMediaTypes []string `json:"supported_media_types"`
+}
+
+// MCP server configuration (local/stdio or remote/http)
+type MCPServerConfig struct {
+ Args []string `json:"args,omitempty"`
+ Command *string `json:"command,omitempty"`
+ Cwd *string `json:"cwd,omitempty"`
+ Env map[string]string `json:"env,omitempty"`
+ FilterMapping *FilterMapping `json:"filterMapping"`
+ IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
+ // Timeout in milliseconds for tool calls to this server.
+ Timeout *int64 `json:"timeout,omitempty"`
+ // Tools to include. Defaults to all tools if not specified.
+ Tools []string `json:"tools,omitempty"`
+ // Remote transport type. Defaults to "http" when omitted.
+ Type *MCPServerConfigType `json:"type,omitempty"`
+ Headers map[string]string `json:"headers,omitempty"`
+ OauthClientID *string `json:"oauthClientId,omitempty"`
+ OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
+ URL *string `json:"url,omitempty"`
+}
+
+type DiscoveredMCPServer struct {
+ // Whether the server is enabled (not in the disabled list)
+ Enabled bool `json:"enabled"`
+ // Server name (config key)
+ Name string `json:"name"`
+ // Configuration source
+ Source MCPServerSource `json:"source"`
+ // Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)
+ Type *DiscoveredMCPServerType `json:"type,omitempty"`
+}
+
+type ServerSkillList struct {
+ // All discovered skills across all sources
+ Skills []SkillElement `json:"skills"`
+}
+
+type SkillElement struct {
+ // Description of what the skill does
+ Description string `json:"description"`
+ // Whether the skill is currently enabled (based on global config)
+ Enabled bool `json:"enabled"`
+ // Unique identifier for the skill
+ Name string `json:"name"`
+ // Absolute path to the skill file
+ Path *string `json:"path,omitempty"`
+ // The project path this skill belongs to (only for project/inherited skills)
+ ProjectPath *string `json:"projectPath,omitempty"`
+ // Source location type (e.g., project, personal-copilot, plugin, builtin)
+ Source string `json:"source"`
+ // Whether the skill can be invoked by the user as a slash command
+ UserInvocable bool `json:"userInvocable"`
+}
+
+type ServerSkill struct {
+ // Description of what the skill does
+ Description string `json:"description"`
+ // Whether the skill is currently enabled (based on global config)
+ Enabled bool `json:"enabled"`
+ // Unique identifier for the skill
+ Name string `json:"name"`
+ // Absolute path to the skill file
+ Path *string `json:"path,omitempty"`
+ // The project path this skill belongs to (only for project/inherited skills)
+ ProjectPath *string `json:"projectPath,omitempty"`
+ // Source location type (e.g., project, personal-copilot, plugin, builtin)
+ Source string `json:"source"`
+ // Whether the skill can be invoked by the user as a slash command
+ UserInvocable bool `json:"userInvocable"`
+}
+
+type CurrentModel struct {
+ // Currently active model identifier
+ ModelID *string `json:"modelId,omitempty"`
+}
+
+// Override individual model capabilities resolved by the runtime
+type ModelCapabilitiesOverride struct {
+ // Token limits for prompts, outputs, and context window
+ Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"`
+ // Feature flags indicating what the model supports
+ Supports *ModelCapabilitiesOverrideSupports `json:"supports,omitempty"`
+}
+
+// Token limits for prompts, outputs, and context window
+type ModelCapabilitiesOverrideLimits struct {
+ // Maximum total context window size in tokens
+ MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"`
+ MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
+ MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"`
+ Vision *PurpleModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"`
+}
+
+type PurpleModelCapabilitiesOverrideLimitsVision struct {
+ // Maximum image size in bytes
+ MaxPromptImageSize *int64 `json:"max_prompt_image_size,omitempty"`
+ // Maximum number of images per prompt
+ MaxPromptImages *int64 `json:"max_prompt_images,omitempty"`
+ // MIME types the model accepts
+ SupportedMediaTypes []string `json:"supported_media_types,omitempty"`
+}
+
+// Feature flags indicating what the model supports
+type ModelCapabilitiesOverrideSupports struct {
+ ReasoningEffort *bool `json:"reasoningEffort,omitempty"`
+ Vision *bool `json:"vision,omitempty"`
+}
+
+type AgentInfo struct {
+ // Description of the agent's purpose
+ Description string `json:"description"`
+ // Human-readable display name
+ DisplayName string `json:"displayName"`
+ // Unique identifier of the custom agent
+ Name string `json:"name"`
+}
+
+type MCPServerList struct {
+ // Configured MCP servers
+ Servers []MCPServer `json:"servers"`
+}
+
+type MCPServer struct {
+ // Error message if the server failed to connect
+ Error *string `json:"error,omitempty"`
+ // Server name (config key)
+ Name string `json:"name"`
+ // Configuration source: user, workspace, plugin, or builtin
+ Source *MCPServerSource `json:"source,omitempty"`
+ // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
+ Status MCPServerStatus `json:"status"`
+}
+
+type ToolCallResult struct {
+ // Error message if the tool call failed
+ Error *string `json:"error,omitempty"`
+ // Type of the tool result
+ ResultType *string `json:"resultType,omitempty"`
+ // Text result to send back to the LLM
+ TextResultForLlm string `json:"textResultForLlm"`
+ // Telemetry data from tool execution
+ ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"`
+}
+
+type HandleToolCallResult struct {
+ // Whether the tool call result was handled successfully
+ Success bool `json:"success"`
+}
+
+type UIElicitationStringEnumField struct {
+ Default *string `json:"default,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Enum []string `json:"enum"`
+ EnumNames []string `json:"enumNames,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Type UIElicitationStringEnumFieldType `json:"type"`
+}
+
+type UIElicitationStringOneOfField struct {
+ Default *string `json:"default,omitempty"`
+ Description *string `json:"description,omitempty"`
+ OneOf []UIElicitationStringOneOfFieldOneOf `json:"oneOf"`
+ Title *string `json:"title,omitempty"`
+ Type UIElicitationStringEnumFieldType `json:"type"`
+}
+
+type UIElicitationStringOneOfFieldOneOf struct {
+ Const string `json:"const"`
+ Title string `json:"title"`
+}
+
+type UIElicitationArrayEnumField struct {
+ Default []string `json:"default,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Items UIElicitationArrayEnumFieldItems `json:"items"`
+ MaxItems *float64 `json:"maxItems,omitempty"`
+ MinItems *float64 `json:"minItems,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Type UIElicitationArrayEnumFieldType `json:"type"`
+}
+
+type UIElicitationArrayEnumFieldItems struct {
+ Enum []string `json:"enum"`
+ Type UIElicitationStringEnumFieldType `json:"type"`
+}
+
+type UIElicitationArrayAnyOfField struct {
+ Default []string `json:"default,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Items UIElicitationArrayAnyOfFieldItems `json:"items"`
+ MaxItems *float64 `json:"maxItems,omitempty"`
+ MinItems *float64 `json:"minItems,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Type UIElicitationArrayEnumFieldType `json:"type"`
+}
+
+type UIElicitationArrayAnyOfFieldItems struct {
+ AnyOf []PurpleUIElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf"`
+}
+
+type PurpleUIElicitationArrayAnyOfFieldItemsAnyOf struct {
+ Const string `json:"const"`
+ Title string `json:"title"`
+}
+
+// The elicitation response (accept with form values, decline, or cancel)
+type UIElicitationResponse struct {
+ // The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+ Action UIElicitationResponseAction `json:"action"`
+ // The form values submitted by the user (present when action is 'accept')
+ Content map[string]*UIElicitationFieldValue `json:"content,omitempty"`
+}
+
+type UIHandlePendingElicitationRequest struct {
+ // The unique request ID from the elicitation.requested event
+ RequestID string `json:"requestId"`
+ // The elicitation response (accept with form values, decline, or cancel)
+ Result UIElicitationResponse `json:"result"`
+}
+
+type UIElicitationResult struct {
+ // Whether the response was accepted. False if the request was already resolved by another
+ // client.
+ Success bool `json:"success"`
+}
+
+type PermissionDecisionRequest struct {
+ // Request ID of the pending permission request
+ RequestID string `json:"requestId"`
+ Result PermissionDecision `json:"result"`
+}
+
+type PermissionDecision struct {
+ // The permission request was approved
+ //
+ // Denied because approval rules explicitly blocked it
+ //
+ // Denied because no approval rule matched and user confirmation was unavailable
+ //
+ // Denied by the user during an interactive prompt
+ //
+ // Denied by the organization's content exclusion policy
+ //
+ // Denied by a permission request hook registered by an extension or plugin
+ Kind Kind `json:"kind"`
+ // Rules that denied the request
+ Rules []any `json:"rules,omitempty"`
+ // Optional feedback from the user explaining the denial
+ Feedback *string `json:"feedback,omitempty"`
+ // Human-readable explanation of why the path was excluded
+ //
+ // Optional message from the hook explaining the denial
+ Message *string `json:"message,omitempty"`
+ // File path that triggered the exclusion
+ Path *string `json:"path,omitempty"`
+ // Whether to interrupt the current agent turn
+ Interrupt *bool `json:"interrupt,omitempty"`
+}
+
+type PermissionRequestResult struct {
+ // Whether the permission request was handled successfully
+ Success bool `json:"success"`
+}
+
type PingResult struct {
// Echoed message (or default greeting)
Message string `json:"message"`
@@ -28,14 +341,14 @@ type PingRequest struct {
type ModelList struct {
// List of available models with full metadata
- Models []Model `json:"models"`
+ Models []ModelElement `json:"models"`
}
-type Model struct {
+type ModelElement struct {
// Billing information
Billing *ModelBilling `json:"billing,omitempty"`
// Model capabilities and limits
- Capabilities ModelCapabilities `json:"capabilities"`
+ Capabilities CapabilitiesClass `json:"capabilities"`
// Default reasoning effort level (only present if model supports reasoning effort)
DefaultReasoningEffort *string `json:"defaultReasoningEffort,omitempty"`
// Model identifier (e.g., "claude-sonnet-4.5")
@@ -55,15 +368,15 @@ type ModelBilling struct {
}
// Model capabilities and limits
-type ModelCapabilities struct {
+type CapabilitiesClass struct {
// Token limits for prompts, outputs, and context window
- Limits *ModelCapabilitiesLimits `json:"limits,omitempty"`
+ Limits *CapabilitiesLimits `json:"limits,omitempty"`
// Feature flags indicating what the model supports
- Supports *ModelCapabilitiesSupports `json:"supports,omitempty"`
+ Supports *CapabilitiesSupports `json:"supports,omitempty"`
}
// Token limits for prompts, outputs, and context window
-type ModelCapabilitiesLimits struct {
+type CapabilitiesLimits struct {
// Maximum total context window size in tokens
MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"`
// Maximum number of output/completion tokens
@@ -71,11 +384,11 @@ type ModelCapabilitiesLimits struct {
// Maximum number of prompt/input tokens
MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"`
// Vision-specific limits
- Vision *ModelCapabilitiesLimitsVision `json:"vision,omitempty"`
+ Vision *FluffyModelCapabilitiesLimitsVision `json:"vision,omitempty"`
}
// Vision-specific limits
-type ModelCapabilitiesLimitsVision struct {
+type FluffyModelCapabilitiesLimitsVision struct {
// Maximum image size in bytes
MaxPromptImageSize int64 `json:"max_prompt_image_size"`
// Maximum number of images per prompt
@@ -85,7 +398,7 @@ type ModelCapabilitiesLimitsVision struct {
}
// Feature flags indicating what the model supports
-type ModelCapabilitiesSupports struct {
+type CapabilitiesSupports struct {
// Whether this model supports reasoning effort configuration
ReasoningEffort *bool `json:"reasoningEffort,omitempty"`
// Whether this model supports vision/image input
@@ -147,27 +460,27 @@ type AccountQuotaSnapshot struct {
type MCPConfigList struct {
// All MCP servers from user config, keyed by name
- Servers map[string]MCPConfigServer `json:"servers"`
+ Servers map[string]MCPServerConfigValue `json:"servers"`
}
// MCP server configuration (local/stdio or remote/http)
-type MCPConfigServer struct {
- Args []string `json:"args,omitempty"`
- Command *string `json:"command,omitempty"`
- Cwd *string `json:"cwd,omitempty"`
- Env map[string]string `json:"env,omitempty"`
- FilterMapping *MCPConfigFilterMapping `json:"filterMapping"`
- IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
+type MCPServerConfigValue struct {
+ Args []string `json:"args,omitempty"`
+ Command *string `json:"command,omitempty"`
+ Cwd *string `json:"cwd,omitempty"`
+ Env map[string]string `json:"env,omitempty"`
+ FilterMapping *FilterMapping `json:"filterMapping"`
+ IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
// Timeout in milliseconds for tool calls to this server.
Timeout *int64 `json:"timeout,omitempty"`
// Tools to include. Defaults to all tools if not specified.
Tools []string `json:"tools,omitempty"`
// Remote transport type. Defaults to "http" when omitted.
- Type *MCPConfigType `json:"type,omitempty"`
- Headers map[string]string `json:"headers,omitempty"`
- OauthClientID *string `json:"oauthClientId,omitempty"`
- OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
- URL *string `json:"url,omitempty"`
+ Type *MCPServerConfigType `json:"type,omitempty"`
+ Headers map[string]string `json:"headers,omitempty"`
+ OauthClientID *string `json:"oauthClientId,omitempty"`
+ OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
+ URL *string `json:"url,omitempty"`
}
type MCPConfigAddResult struct {
@@ -175,29 +488,29 @@ type MCPConfigAddResult struct {
type MCPConfigAddRequest struct {
// MCP server configuration (local/stdio or remote/http)
- Config MCPConfigAddConfig `json:"config"`
+ Config MCPConfigAddRequestMCPServerConfig `json:"config"`
// Unique name for the MCP server
Name string `json:"name"`
}
// MCP server configuration (local/stdio or remote/http)
-type MCPConfigAddConfig struct {
- Args []string `json:"args,omitempty"`
- Command *string `json:"command,omitempty"`
- Cwd *string `json:"cwd,omitempty"`
- Env map[string]string `json:"env,omitempty"`
- FilterMapping *MCPConfigFilterMapping `json:"filterMapping"`
- IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
+type MCPConfigAddRequestMCPServerConfig struct {
+ Args []string `json:"args,omitempty"`
+ Command *string `json:"command,omitempty"`
+ Cwd *string `json:"cwd,omitempty"`
+ Env map[string]string `json:"env,omitempty"`
+ FilterMapping *FilterMapping `json:"filterMapping"`
+ IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
// Timeout in milliseconds for tool calls to this server.
Timeout *int64 `json:"timeout,omitempty"`
// Tools to include. Defaults to all tools if not specified.
Tools []string `json:"tools,omitempty"`
// Remote transport type. Defaults to "http" when omitted.
- Type *MCPConfigType `json:"type,omitempty"`
- Headers map[string]string `json:"headers,omitempty"`
- OauthClientID *string `json:"oauthClientId,omitempty"`
- OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
- URL *string `json:"url,omitempty"`
+ Type *MCPServerConfigType `json:"type,omitempty"`
+ Headers map[string]string `json:"headers,omitempty"`
+ OauthClientID *string `json:"oauthClientId,omitempty"`
+ OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
+ URL *string `json:"url,omitempty"`
}
type MCPConfigUpdateResult struct {
@@ -205,29 +518,29 @@ type MCPConfigUpdateResult struct {
type MCPConfigUpdateRequest struct {
// MCP server configuration (local/stdio or remote/http)
- Config MCPConfigUpdateConfig `json:"config"`
+ Config MCPConfigUpdateRequestMCPServerConfig `json:"config"`
// Name of the MCP server to update
Name string `json:"name"`
}
// MCP server configuration (local/stdio or remote/http)
-type MCPConfigUpdateConfig struct {
- Args []string `json:"args,omitempty"`
- Command *string `json:"command,omitempty"`
- Cwd *string `json:"cwd,omitempty"`
- Env map[string]string `json:"env,omitempty"`
- FilterMapping *MCPConfigFilterMapping `json:"filterMapping"`
- IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
+type MCPConfigUpdateRequestMCPServerConfig struct {
+ Args []string `json:"args,omitempty"`
+ Command *string `json:"command,omitempty"`
+ Cwd *string `json:"cwd,omitempty"`
+ Env map[string]string `json:"env,omitempty"`
+ FilterMapping *FilterMapping `json:"filterMapping"`
+ IsDefaultServer *bool `json:"isDefaultServer,omitempty"`
// Timeout in milliseconds for tool calls to this server.
Timeout *int64 `json:"timeout,omitempty"`
// Tools to include. Defaults to all tools if not specified.
Tools []string `json:"tools,omitempty"`
// Remote transport type. Defaults to "http" when omitted.
- Type *MCPConfigType `json:"type,omitempty"`
- Headers map[string]string `json:"headers,omitempty"`
- OauthClientID *string `json:"oauthClientId,omitempty"`
- OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
- URL *string `json:"url,omitempty"`
+ Type *MCPServerConfigType `json:"type,omitempty"`
+ Headers map[string]string `json:"headers,omitempty"`
+ OauthClientID *string `json:"oauthClientId,omitempty"`
+ OauthPublicClient *bool `json:"oauthPublicClient,omitempty"`
+ URL *string `json:"url,omitempty"`
}
type MCPConfigRemoveResult struct {
@@ -240,10 +553,10 @@ type MCPConfigRemoveRequest struct {
type MCPDiscoverResult struct {
// MCP servers discovered from all sources
- Servers []DiscoveredMCPServer `json:"servers"`
+ Servers []ServerElement `json:"servers"`
}
-type DiscoveredMCPServer struct {
+type ServerElement struct {
// Whether the server is enabled (not in the disabled list)
Enabled bool `json:"enabled"`
// Server name (config key)
@@ -267,28 +580,6 @@ type SkillsConfigSetDisabledSkillsRequest struct {
DisabledSkills []string `json:"disabledSkills"`
}
-type ServerSkillList struct {
- // All discovered skills across all sources
- Skills []ServerSkill `json:"skills"`
-}
-
-type ServerSkill struct {
- // Description of what the skill does
- Description string `json:"description"`
- // Whether the skill is currently enabled (based on global config)
- Enabled bool `json:"enabled"`
- // Unique identifier for the skill
- Name string `json:"name"`
- // Absolute path to the skill file
- Path *string `json:"path,omitempty"`
- // The project path this skill belongs to (only for project/inherited skills)
- ProjectPath *string `json:"projectPath,omitempty"`
- // Source location type (e.g., project, personal-copilot, plugin, builtin)
- Source string `json:"source"`
- // Whether the skill can be invoked by the user as a slash command
- UserInvocable bool `json:"userInvocable"`
-}
-
type SkillsDiscoverRequest struct {
// Optional list of project directory paths to scan for project-scoped skills
ProjectPaths []string `json:"projectPaths,omitempty"`
@@ -325,11 +616,6 @@ type SessionsForkRequest struct {
ToEventID *string `json:"toEventId,omitempty"`
}
-type CurrentModel struct {
- // Currently active model identifier
- ModelID *string `json:"modelId,omitempty"`
-}
-
type ModelSwitchToResult struct {
// Currently active model identifier after the switch
ModelID *string `json:"modelId,omitempty"`
@@ -337,7 +623,7 @@ type ModelSwitchToResult struct {
type ModelSwitchToRequest struct {
// Override individual model capabilities resolved by the runtime
- ModelCapabilities *ModelCapabilitiesOverride `json:"modelCapabilities,omitempty"`
+ ModelCapabilities *ModelCapabilitiesClass `json:"modelCapabilities,omitempty"`
// Model identifier to switch to
ModelID string `json:"modelId"`
// Reasoning effort level to use for the model
@@ -345,23 +631,23 @@ type ModelSwitchToRequest struct {
}
// Override individual model capabilities resolved by the runtime
-type ModelCapabilitiesOverride struct {
+type ModelCapabilitiesClass struct {
// Token limits for prompts, outputs, and context window
- Limits *ModelCapabilitiesOverrideLimits `json:"limits,omitempty"`
+ Limits *ModelCapabilitiesLimitsClass `json:"limits,omitempty"`
// Feature flags indicating what the model supports
Supports *ModelCapabilitiesOverrideSupports `json:"supports,omitempty"`
}
// Token limits for prompts, outputs, and context window
-type ModelCapabilitiesOverrideLimits struct {
+type ModelCapabilitiesLimitsClass struct {
// Maximum total context window size in tokens
- MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"`
- MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
- MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"`
- Vision *ModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"`
+ MaxContextWindowTokens *int64 `json:"max_context_window_tokens,omitempty"`
+ MaxOutputTokens *int64 `json:"max_output_tokens,omitempty"`
+ MaxPromptTokens *int64 `json:"max_prompt_tokens,omitempty"`
+ Vision *FluffyModelCapabilitiesOverrideLimitsVision `json:"vision,omitempty"`
}
-type ModelCapabilitiesOverrideLimitsVision struct {
+type FluffyModelCapabilitiesOverrideLimitsVision struct {
// Maximum image size in bytes
MaxPromptImageSize *int64 `json:"max_prompt_image_size,omitempty"`
// Maximum number of images per prompt
@@ -370,12 +656,6 @@ type ModelCapabilitiesOverrideLimitsVision struct {
SupportedMediaTypes []string `json:"supported_media_types,omitempty"`
}
-// Feature flags indicating what the model supports
-type ModelCapabilitiesOverrideSupports struct {
- ReasoningEffort *bool `json:"reasoningEffort,omitempty"`
- Vision *bool `json:"vision,omitempty"`
-}
-
type ModeSetResult struct {
}
@@ -467,6 +747,30 @@ type WorkspacesCreateFileRequest struct {
Path string `json:"path"`
}
+type InstructionsGetSourcesResult struct {
+ // Instruction sources for the session
+ Sources []InstructionsSources `json:"sources"`
+}
+
+type InstructionsSources struct {
+ // Glob pattern 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"`
+ // Short description (body after frontmatter) for use in instruction tables
+ Description *string `json:"description,omitempty"`
+ // Unique identifier for this source (used for toggling)
+ ID string `json:"id"`
+ // Human-readable label
+ Label string `json:"label"`
+ // Where this source lives — used for UI grouping
+ Location InstructionsSourcesLocation `json:"location"`
+ // File path relative to repo or absolute for home
+ SourcePath string `json:"sourcePath"`
+ // Category of instruction source — used for merge logic
+ Type InstructionsSourcesType `json:"type"`
+}
+
// Experimental: FleetStartResult is part of an experimental API and may change or be removed.
type FleetStartResult struct {
// Whether fleet mode was successfully activated
@@ -482,10 +786,10 @@ type FleetStartRequest struct {
// Experimental: AgentList is part of an experimental API and may change or be removed.
type AgentList struct {
// Available custom agents
- Agents []Agent `json:"agents"`
+ Agents []AgentListAgent `json:"agents"`
}
-type Agent struct {
+type AgentListAgent struct {
// Description of the agent's purpose
Description string `json:"description"`
// Human-readable display name
@@ -497,26 +801,17 @@ type Agent struct {
// Experimental: AgentGetCurrentResult is part of an experimental API and may change or be removed.
type AgentGetCurrentResult struct {
// Currently selected custom agent, or null if using the default agent
- Agent *AgentGetCurrentResultAgent `json:"agent"`
-}
-
-type AgentGetCurrentResultAgent struct {
- // Description of the agent's purpose
- Description string `json:"description"`
- // Human-readable display name
- DisplayName string `json:"displayName"`
- // Unique identifier of the custom agent
- Name string `json:"name"`
+ Agent *AgentReloadResultAgent `json:"agent"`
}
// Experimental: AgentSelectResult is part of an experimental API and may change or be removed.
type AgentSelectResult struct {
// The newly selected custom agent
- Agent AgentSelectAgent `json:"agent"`
+ Agent AgentSelectResultAgent `json:"agent"`
}
// The newly selected custom agent
-type AgentSelectAgent struct {
+type AgentSelectResultAgent struct {
// Description of the agent's purpose
Description string `json:"description"`
// Human-readable display name
@@ -538,10 +833,10 @@ type AgentDeselectResult struct {
// Experimental: AgentReloadResult is part of an experimental API and may change or be removed.
type AgentReloadResult struct {
// Reloaded custom agents
- Agents []AgentReloadAgent `json:"agents"`
+ Agents []AgentReloadResultAgent `json:"agents"`
}
-type AgentReloadAgent struct {
+type AgentReloadResultAgent struct {
// Description of the agent's purpose
Description string `json:"description"`
// Human-readable display name
@@ -595,22 +890,6 @@ type SkillsDisableRequest struct {
type SkillsReloadResult struct {
}
-type MCPServerList struct {
- // Configured MCP servers
- Servers []MCPServer `json:"servers"`
-}
-
-type MCPServer struct {
- // Error message if the server failed to connect
- Error *string `json:"error,omitempty"`
- // Server name (config key)
- Name string `json:"name"`
- // Configuration source: user, workspace, plugin, or builtin
- Source *MCPServerSource `json:"source,omitempty"`
- // Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
- Status MCPServerStatus `json:"status"`
-}
-
type MCPEnableResult struct {
}
@@ -690,11 +969,6 @@ type ExtensionsDisableRequest struct {
type ExtensionsReloadResult struct {
}
-type HandleToolCallResult struct {
- // Whether the tool call result was handled successfully
- Success bool `json:"success"`
-}
-
type ToolsHandlePendingToolCallRequest struct {
// Error message if the tool call failed
Error *string `json:"error,omitempty"`
@@ -704,17 +978,6 @@ type ToolsHandlePendingToolCallRequest struct {
Result *ToolsHandlePendingToolCall `json:"result"`
}
-type ToolCallResult struct {
- // Error message if the tool call failed
- Error *string `json:"error,omitempty"`
- // Type of the tool result
- ResultType *string `json:"resultType,omitempty"`
- // Text result to send back to the LLM
- TextResultForLlm string `json:"textResultForLlm"`
- // Telemetry data from tool execution
- ToolTelemetry map[string]any `json:"toolTelemetry,omitempty"`
-}
-
type CommandsHandlePendingCommandResult struct {
// Whether the command was handled successfully
Success bool `json:"success"`
@@ -727,14 +990,6 @@ type CommandsHandlePendingCommandRequest struct {
RequestID string `json:"requestId"`
}
-// The elicitation response (accept with form values, decline, or cancel)
-type UIElicitationResponse struct {
- // The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
- Action UIElicitationResponseAction `json:"action"`
- // The form values submitted by the user (present when action is 'accept')
- Content map[string]*UIElicitationFieldValue `json:"content,omitempty"`
-}
-
type UIElicitationRequest struct {
// Message describing what information is needed from the user
Message string `json:"message"`
@@ -759,7 +1014,7 @@ type UIElicitationSchemaProperty struct {
EnumNames []string `json:"enumNames,omitempty"`
Title *string `json:"title,omitempty"`
Type UIElicitationSchemaPropertyNumberType `json:"type"`
- OneOf []UIElicitationStringOneOfFieldOneOf `json:"oneOf,omitempty"`
+ OneOf []UIElicitationSchemaPropertyOneOf `json:"oneOf,omitempty"`
Items *UIElicitationArrayFieldItems `json:"items,omitempty"`
MaxItems *float64 `json:"maxItems,omitempty"`
MinItems *float64 `json:"minItems,omitempty"`
@@ -771,72 +1026,21 @@ type UIElicitationSchemaProperty struct {
}
type UIElicitationArrayFieldItems struct {
- Enum []string `json:"enum,omitempty"`
- Type *ItemsType `json:"type,omitempty"`
- AnyOf []UIElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"`
+ Enum []string `json:"enum,omitempty"`
+ Type *UIElicitationStringEnumFieldType `json:"type,omitempty"`
+ AnyOf []FluffyUIElicitationArrayAnyOfFieldItemsAnyOf `json:"anyOf,omitempty"`
}
-type UIElicitationArrayAnyOfFieldItemsAnyOf struct {
+type FluffyUIElicitationArrayAnyOfFieldItemsAnyOf struct {
Const string `json:"const"`
Title string `json:"title"`
}
-type UIElicitationStringOneOfFieldOneOf struct {
+type UIElicitationSchemaPropertyOneOf struct {
Const string `json:"const"`
Title string `json:"title"`
}
-type UIElicitationResult struct {
- // Whether the response was accepted. False if the request was already resolved by another
- // client.
- Success bool `json:"success"`
-}
-
-type UIHandlePendingElicitationRequest struct {
- // The unique request ID from the elicitation.requested event
- RequestID string `json:"requestId"`
- // The elicitation response (accept with form values, decline, or cancel)
- Result UIElicitationResponse `json:"result"`
-}
-
-type PermissionRequestResult struct {
- // Whether the permission request was handled successfully
- Success bool `json:"success"`
-}
-
-type PermissionDecisionRequest struct {
- // Request ID of the pending permission request
- RequestID string `json:"requestId"`
- Result PermissionDecision `json:"result"`
-}
-
-type PermissionDecision struct {
- // The permission request was approved
- //
- // Denied because approval rules explicitly blocked it
- //
- // Denied because no approval rule matched and user confirmation was unavailable
- //
- // Denied by the user during an interactive prompt
- //
- // Denied by the organization's content exclusion policy
- //
- // Denied by a permission request hook registered by an extension or plugin
- Kind Kind `json:"kind"`
- // Rules that denied the request
- Rules []any `json:"rules,omitempty"`
- // Optional feedback from the user explaining the denial
- Feedback *string `json:"feedback,omitempty"`
- // Human-readable explanation of why the path was excluded
- //
- // Optional message from the hook explaining the denial
- Message *string `json:"message,omitempty"`
- // File path that triggered the exclusion
- Path *string `json:"path,omitempty"`
- // Whether to interrupt the current agent turn
- Interrupt *bool `json:"interrupt,omitempty"`
-}
-
type LogResult struct {
// The unique identifier of the emitted session event
EventID string `json:"eventId"`
@@ -1125,22 +1329,22 @@ type SessionFSRenameRequest struct {
Src string `json:"src"`
}
-type MCPConfigFilterMappingString string
+type FilterMappingString string
const (
- MCPConfigFilterMappingStringHiddenCharacters MCPConfigFilterMappingString = "hidden_characters"
- MCPConfigFilterMappingStringMarkdown MCPConfigFilterMappingString = "markdown"
- MCPConfigFilterMappingStringNone MCPConfigFilterMappingString = "none"
+ FilterMappingStringHiddenCharacters FilterMappingString = "hidden_characters"
+ FilterMappingStringMarkdown FilterMappingString = "markdown"
+ FilterMappingStringNone FilterMappingString = "none"
)
// Remote transport type. Defaults to "http" when omitted.
-type MCPConfigType string
+type MCPServerConfigType string
const (
- MCPConfigTypeHTTP MCPConfigType = "http"
- MCPConfigTypeLocal MCPConfigType = "local"
- MCPConfigTypeSSE MCPConfigType = "sse"
- MCPConfigTypeStdio MCPConfigType = "stdio"
+ MCPServerConfigTypeHTTP MCPServerConfigType = "http"
+ MCPServerConfigTypeLocal MCPServerConfigType = "local"
+ MCPServerConfigTypeSSE MCPServerConfigType = "sse"
+ MCPServerConfigTypeStdio MCPServerConfigType = "stdio"
)
// Configuration source
@@ -1165,6 +1369,50 @@ const (
DiscoveredMCPServerTypeMemory DiscoveredMCPServerType = "memory"
)
+// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
+type MCPServerStatus string
+
+const (
+ MCPServerStatusConnected MCPServerStatus = "connected"
+ MCPServerStatusDisabled MCPServerStatus = "disabled"
+ MCPServerStatusFailed MCPServerStatus = "failed"
+ MCPServerStatusNeedsAuth MCPServerStatus = "needs-auth"
+ MCPServerStatusNotConfigured MCPServerStatus = "not_configured"
+ MCPServerStatusPending MCPServerStatus = "pending"
+)
+
+type UIElicitationStringEnumFieldType string
+
+const (
+ UIElicitationStringEnumFieldTypeString UIElicitationStringEnumFieldType = "string"
+)
+
+type UIElicitationArrayEnumFieldType string
+
+const (
+ UIElicitationArrayEnumFieldTypeArray UIElicitationArrayEnumFieldType = "array"
+)
+
+// The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+type UIElicitationResponseAction string
+
+const (
+ UIElicitationResponseActionAccept UIElicitationResponseAction = "accept"
+ UIElicitationResponseActionCancel UIElicitationResponseAction = "cancel"
+ UIElicitationResponseActionDecline UIElicitationResponseAction = "decline"
+)
+
+type Kind string
+
+const (
+ KindApproved Kind = "approved"
+ KindDeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy"
+ KindDeniedByPermissionRequestHook Kind = "denied-by-permission-request-hook"
+ KindDeniedByRules Kind = "denied-by-rules"
+ KindDeniedInteractivelyByUser Kind = "denied-interactively-by-user"
+ KindDeniedNoApprovalRuleAndCouldNotRequestFromUser Kind = "denied-no-approval-rule-and-could-not-request-from-user"
+)
+
// Path conventions used by this filesystem
type SessionFSSetProviderConventions string
@@ -1197,16 +1445,25 @@ const (
SessionSyncLevelUser SessionSyncLevel = "user"
)
-// Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
-type MCPServerStatus string
+// Where this source lives — used for UI grouping
+type InstructionsSourcesLocation string
const (
- MCPServerStatusConnected MCPServerStatus = "connected"
- MCPServerStatusDisabled MCPServerStatus = "disabled"
- MCPServerStatusFailed MCPServerStatus = "failed"
- MCPServerStatusNeedsAuth MCPServerStatus = "needs-auth"
- MCPServerStatusNotConfigured MCPServerStatus = "not_configured"
- MCPServerStatusPending MCPServerStatus = "pending"
+ InstructionsSourcesLocationUser InstructionsSourcesLocation = "user"
+ InstructionsSourcesLocationRepository InstructionsSourcesLocation = "repository"
+ 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"
+ InstructionsSourcesTypeRepo InstructionsSourcesType = "repo"
+ InstructionsSourcesTypeVscode InstructionsSourcesType = "vscode"
)
// Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)
@@ -1227,15 +1484,6 @@ const (
ExtensionStatusStarting ExtensionStatus = "starting"
)
-// The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
-type UIElicitationResponseAction string
-
-const (
- UIElicitationResponseActionAccept UIElicitationResponseAction = "accept"
- UIElicitationResponseActionCancel UIElicitationResponseAction = "cancel"
- UIElicitationResponseActionDecline UIElicitationResponseAction = "decline"
-)
-
type UIElicitationSchemaPropertyStringFormat string
const (
@@ -1245,19 +1493,13 @@ const (
UIElicitationSchemaPropertyStringFormatURI UIElicitationSchemaPropertyStringFormat = "uri"
)
-type ItemsType string
-
-const (
- ItemsTypeString ItemsType = "string"
-)
-
type UIElicitationSchemaPropertyNumberType string
const (
- UIElicitationSchemaPropertyNumberTypeArray UIElicitationSchemaPropertyNumberType = "array"
UIElicitationSchemaPropertyNumberTypeBoolean UIElicitationSchemaPropertyNumberType = "boolean"
UIElicitationSchemaPropertyNumberTypeInteger UIElicitationSchemaPropertyNumberType = "integer"
UIElicitationSchemaPropertyNumberTypeNumber UIElicitationSchemaPropertyNumberType = "number"
+ UIElicitationSchemaPropertyNumberTypeArray UIElicitationSchemaPropertyNumberType = "array"
UIElicitationSchemaPropertyNumberTypeString UIElicitationSchemaPropertyNumberType = "string"
)
@@ -1267,17 +1509,6 @@ const (
RequestedSchemaTypeObject RequestedSchemaType = "object"
)
-type Kind string
-
-const (
- KindApproved Kind = "approved"
- KindDeniedByContentExclusionPolicy Kind = "denied-by-content-exclusion-policy"
- KindDeniedByPermissionRequestHook Kind = "denied-by-permission-request-hook"
- KindDeniedByRules Kind = "denied-by-rules"
- KindDeniedInteractivelyByUser Kind = "denied-interactively-by-user"
- KindDeniedNoApprovalRuleAndCouldNotRequestFromUser Kind = "denied-no-approval-rule-and-could-not-request-from-user"
-)
-
// Log severity level. Determines how the message is displayed in the timeline. Defaults to
// "info".
type SessionLogLevel string
@@ -1305,15 +1536,9 @@ const (
SessionFSReaddirWithTypesEntryTypeFile SessionFSReaddirWithTypesEntryType = "file"
)
-type MCPConfigFilterMapping struct {
- Enum *MCPConfigFilterMappingString
- EnumMap map[string]MCPConfigFilterMappingString
-}
-
-// Tool call result (string or expanded result object)
-type ToolsHandlePendingToolCall struct {
- String *string
- ToolCallResult *ToolCallResult
+type FilterMapping struct {
+ Enum *FilterMappingString
+ EnumMap map[string]FilterMappingString
}
type UIElicitationFieldValue struct {
@@ -1323,6 +1548,12 @@ type UIElicitationFieldValue struct {
StringArray []string
}
+// Tool call result (string or expanded result object)
+type ToolsHandlePendingToolCall struct {
+ String *string
+ ToolCallResult *ToolCallResult
+}
+
type serverApi struct {
client *jsonrpc2.Client
}
@@ -1745,6 +1976,21 @@ func (a *WorkspacesApi) CreateFile(ctx context.Context, params *WorkspacesCreate
return &result, nil
}
+type InstructionsApi sessionApi
+
+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: FleetApi contains experimental APIs that may change or be removed.
type FleetApi sessionApi
@@ -2231,24 +2477,25 @@ func (a *UsageApi) GetMetrics(ctx context.Context) (*UsageGetMetricsResult, erro
type SessionRpc struct {
common sessionApi // Reuse a single struct instead of allocating one for each service on the heap.
- Model *ModelApi
- Mode *ModeApi
- Name *NameApi
- Plan *PlanApi
- Workspaces *WorkspacesApi
- Fleet *FleetApi
- Agent *AgentApi
- Skills *SkillsApi
- Mcp *McpApi
- Plugins *PluginsApi
- Extensions *ExtensionsApi
- Tools *ToolsApi
- Commands *CommandsApi
- UI *UIApi
- Permissions *PermissionsApi
- Shell *ShellApi
- History *HistoryApi
- Usage *UsageApi
+ Model *ModelApi
+ Mode *ModeApi
+ Name *NameApi
+ Plan *PlanApi
+ Workspaces *WorkspacesApi
+ Instructions *InstructionsApi
+ Fleet *FleetApi
+ Agent *AgentApi
+ Skills *SkillsApi
+ Mcp *McpApi
+ Plugins *PluginsApi
+ Extensions *ExtensionsApi
+ Tools *ToolsApi
+ Commands *CommandsApi
+ UI *UIApi
+ Permissions *PermissionsApi
+ Shell *ShellApi
+ History *HistoryApi
+ Usage *UsageApi
}
func (a *SessionRpc) Log(ctx context.Context, params *LogRequest) (*LogResult, error) {
@@ -2284,6 +2531,7 @@ func NewSessionRpc(client *jsonrpc2.Client, sessionID string) *SessionRpc {
r.Name = (*NameApi)(&r.common)
r.Plan = (*PlanApi)(&r.common)
r.Workspaces = (*WorkspacesApi)(&r.common)
+ r.Instructions = (*InstructionsApi)(&r.common)
r.Fleet = (*FleetApi)(&r.common)
r.Agent = (*AgentApi)(&r.common)
r.Skills = (*SkillsApi)(&r.common)
diff --git a/go/session.go b/go/session.go
index be8c78e2b..bf42bf03a 100644
--- a/go/session.go
+++ b/go/session.go
@@ -1213,7 +1213,7 @@ func (s *Session) SetModel(ctx context.Context, model string, opts *SetModelOpti
params := &rpc.ModelSwitchToRequest{ModelID: model}
if opts != nil {
params.ReasoningEffort = opts.ReasoningEffort
- params.ModelCapabilities = opts.ModelCapabilities
+ params.ModelCapabilities = convertModelCapabilitiesToClass(opts.ModelCapabilities)
}
_, err := s.RPC.Model.SwitchTo(ctx, params)
if err != nil {
@@ -1223,7 +1223,34 @@ func (s *Session) SetModel(ctx context.Context, model string, opts *SetModelOpti
return nil
}
-// LogOptions configures optional parameters for [Session.Log].
+// convertModelCapabilitiesToClass converts from ModelCapabilitiesOverride
+// (used in the public API) to ModelCapabilitiesClass (used internally by
+// the ModelSwitchToRequest RPC). The two types are structurally identical
+// but have different Go types due to code generation.
+func convertModelCapabilitiesToClass(src *rpc.ModelCapabilitiesOverride) *rpc.ModelCapabilitiesClass {
+ if src == nil {
+ return nil
+ }
+ dst := &rpc.ModelCapabilitiesClass{
+ Supports: src.Supports,
+ }
+ if src.Limits != nil {
+ dst.Limits = &rpc.ModelCapabilitiesLimitsClass{
+ MaxContextWindowTokens: src.Limits.MaxContextWindowTokens,
+ MaxOutputTokens: src.Limits.MaxOutputTokens,
+ MaxPromptTokens: src.Limits.MaxPromptTokens,
+ }
+ if src.Limits.Vision != nil {
+ dst.Limits.Vision = &rpc.FluffyModelCapabilitiesOverrideLimitsVision{
+ MaxPromptImageSize: src.Limits.Vision.MaxPromptImageSize,
+ MaxPromptImages: src.Limits.Vision.MaxPromptImages,
+ SupportedMediaTypes: src.Limits.Vision.SupportedMediaTypes,
+ }
+ }
+ }
+ return dst
+}
+
type LogOptions struct {
// Level sets the log severity. Valid values are [rpc.SessionLogLevelInfo] (default),
// [rpc.SessionLogLevelWarning], and [rpc.SessionLogLevelError].
diff --git a/go/types.go b/go/types.go
index f889d3e2a..15c62cec0 100644
--- a/go/types.go
+++ b/go/types.go
@@ -848,7 +848,7 @@ type (
ModelCapabilitiesOverride = rpc.ModelCapabilitiesOverride
ModelCapabilitiesOverrideSupports = rpc.ModelCapabilitiesOverrideSupports
ModelCapabilitiesOverrideLimits = rpc.ModelCapabilitiesOverrideLimits
- ModelCapabilitiesOverrideLimitsVision = rpc.ModelCapabilitiesOverrideLimitsVision
+ ModelCapabilitiesOverrideLimitsVision = rpc.PurpleModelCapabilitiesOverrideLimitsVision
)
// ModelPolicy contains model policy state
diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json
index 002edfbf3..9ccf85c04 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.30",
+ "@github/copilot": "^1.0.32-1",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -663,26 +663,26 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.30.tgz",
- "integrity": "sha512-JYZNMM6hteAE6tIMbHobRjpAaXzvqeeglXgGlDCr26rRq3K6h5ul2GN27qzhMBaWyujUQN402KLKdrhDPqcL7A==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.32-1.tgz",
+ "integrity": "sha512-uJgZWkd+gYS6t8NeWgZd+KDlQ41RFvAydOPdJqMDdB8aBwJYKQA75AVQzJyIne/CaMmv2Cy24X+IeRsMXvg+YA==",
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.30",
- "@github/copilot-darwin-x64": "1.0.30",
- "@github/copilot-linux-arm64": "1.0.30",
- "@github/copilot-linux-x64": "1.0.30",
- "@github/copilot-win32-arm64": "1.0.30",
- "@github/copilot-win32-x64": "1.0.30"
+ "@github/copilot-darwin-arm64": "1.0.32-1",
+ "@github/copilot-darwin-x64": "1.0.32-1",
+ "@github/copilot-linux-arm64": "1.0.32-1",
+ "@github/copilot-linux-x64": "1.0.32-1",
+ "@github/copilot-win32-arm64": "1.0.32-1",
+ "@github/copilot-win32-x64": "1.0.32-1"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.30.tgz",
- "integrity": "sha512-qhLMhAY7nskG6yabbsWSqErxPWcZLX1ixJBdQX3RLqgw5dyNvZRNzG2evUnABo5bqgndztsFXjE3u4XtfX0WkA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-MGz9kKJYqrfZ94DOVsKy8c0sTFn1Gax60hM3TjMt6K+Tt7n8vGhrpBn+KjFYOb+6+r7fp3E7fc6tTtwjgaURVw==",
"cpu": [
"arm64"
],
@@ -696,9 +696,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.30.tgz",
- "integrity": "sha512-nsjGRt1jLBzCaVd6eb3ok75zqePr8eU8GSTqu1KVf5KUrnvvfIlsvESkEAE8l+lkR14f7SGQLfMJ2EEbcJMGcg==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.32-1.tgz",
+ "integrity": "sha512-HSLJXMVk2yf6Xb6NhNxEYvD57hBGdWs5zQ7EOHrFYO+qA5/iD4JVGgQNg7sS88+qsTR5PtEcxwbtQPid1KZJnQ==",
"cpu": [
"x64"
],
@@ -712,9 +712,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.30.tgz",
- "integrity": "sha512-7wOrOKm9MHnglyzzGeZnXSkfRi4sXB2Db7rK/CgUenxS+dwwIuXhT4rgkH/DIOiDbGCxYjigICxln28Jvbs+cA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-XBiX4947+ygPugwsZrrVOwftIWWASoknq1FzehIpj7BqPxjwTpzDXPDJNleHf+6a1cGm8cUutDn/wslHjJEW9A==",
"cpu": [
"arm64"
],
@@ -728,9 +728,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.30.tgz",
- "integrity": "sha512-OSJtP7mV9vnDzGFjBkI3sgbNOcxsRcq7vXrT4PNrjJw4Mc71aaW55hc5F1j2fElfGWIb+Jubm3AB8nb6AoufnA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.32-1.tgz",
+ "integrity": "sha512-iJkcWKSoaDY5GKtOZtoZV5YhuOqvVSdENashNKjXzkIoFN0mqonIhsbAv3OB2Kr34ZwoQF3CfNoOCNBs2tg8pg==",
"cpu": [
"x64"
],
@@ -744,9 +744,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.30.tgz",
- "integrity": "sha512-5nCz/+9VWJdNvW2uRYeMmnRdQq/gpuSlmYMvRv8fIsFF8KH0mdJndJn8xN6GeJtx0fKJrLzgKqJHWdgb5MtLgA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-U/lfmWAqOIxucqotmsOsJtOjfAhNIYAFeqxyaKo+V35YkurXZGTNjB2YxqUlmKm/7fuOgAACHKvrK+tWs+Mlvg==",
"cpu": [
"arm64"
],
@@ -760,9 +760,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.30.tgz",
- "integrity": "sha512-tJvgCsWLJVQvHLvFyQZ0P5MQ7YGX51/bl9kbXDUFCGATtPpELul3NyHWwEYGjRv+VDPvhFxjbf+V7Bf/VzYZ7w==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.32-1.tgz",
+ "integrity": "sha512-oSNG9nRHsyTdi2miBfti4egT+CHPGu0QTXXUasISsfwhex6SS4qeVFe8mt8/clnTlyJD9N7EDgABDduSYQv87g==",
"cpu": [
"x64"
],
diff --git a/nodejs/package.json b/nodejs/package.json
index 7576406df..2ccb7632c 100644
--- a/nodejs/package.json
+++ b/nodejs/package.json
@@ -56,7 +56,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.30",
+ "@github/copilot": "^1.0.32-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 574f9878b..7281be70f 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.30",
+ "@github/copilot": "^1.0.32-1",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts
index c5b84a6d4..a3d50d5ff 100644
--- a/nodejs/src/client.ts
+++ b/nodejs/src/client.ts
@@ -1019,6 +1019,26 @@ export class CopilotClient {
const result = await this.connection.sendRequest("models.list", {});
const response = result as { models: ModelInfo[] };
models = response.models;
+
+ // Normalize model capabilities — some models (e.g. embedding models)
+ // may omit 'supports' or 'limits' in their capabilities.
+ for (const model of models) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const m = model as any;
+ if (!m.capabilities) {
+ m.capabilities = {
+ supports: {},
+ limits: { max_context_window_tokens: 0 },
+ };
+ } else {
+ if (!m.capabilities.supports) m.capabilities.supports = {};
+ if (!m.capabilities.limits) {
+ m.capabilities.limits = { max_context_window_tokens: 0 };
+ } else if (m.capabilities.limits.max_context_window_tokens === undefined) {
+ m.capabilities.limits.max_context_window_tokens = 0;
+ }
+ }
+ }
}
// Update cache before releasing lock (copy to prevent external mutation)
diff --git a/nodejs/src/generated/rpc.ts b/nodejs/src/generated/rpc.ts
index ff60d2534..dedfa8068 100644
--- a/nodejs/src/generated/rpc.ts
+++ b/nodejs/src/generated/rpc.ts
@@ -5,6 +5,60 @@
import type { MessageConnection } from "vscode-jsonrpc/node.js";
+/**
+ * MCP server configuration (local/stdio or remote/http)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "McpServerConfig".
+ */
+export type McpServerConfig =
+ | {
+ /**
+ * Tools to include. Defaults to all tools if not specified.
+ */
+ tools?: string[];
+ type?: "local" | "stdio";
+ isDefaultServer?: boolean;
+ filterMapping?: FilterMapping;
+ /**
+ * Timeout in milliseconds for tool calls to this server.
+ */
+ timeout?: number;
+ command: string;
+ args: string[];
+ cwd?: string;
+ env?: {
+ [k: string]: string;
+ };
+ }
+ | {
+ /**
+ * Tools to include. Defaults to all tools if not specified.
+ */
+ tools?: string[];
+ /**
+ * Remote transport type. Defaults to "http" when omitted.
+ */
+ type?: "http" | "sse";
+ isDefaultServer?: boolean;
+ filterMapping?: FilterMapping;
+ /**
+ * Timeout in milliseconds for tool calls to this server.
+ */
+ timeout?: number;
+ url: string;
+ headers?: {
+ [k: string]: string;
+ };
+ oauthClientId?: string;
+ oauthPublicClient?: boolean;
+ };
+
+export type FilterMapping =
+ | {
+ [k: string]: "none" | "markdown" | "hidden_characters";
+ }
+ | ("none" | "markdown" | "hidden_characters");
/**
* The agent mode. Valid values: "interactive", "plan", "autopilot".
*
@@ -12,11 +66,16 @@ import type { MessageConnection } from "vscode-jsonrpc/node.js";
* via the `definition` "SessionMode".
*/
export type SessionMode = "interactive" | "plan" | "autopilot";
+
+export type UIElicitationFieldValue = string | number | boolean | string[];
/**
* The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "UIElicitationResponseAction".
*/
export type UIElicitationResponseAction = "accept" | "decline" | "cancel";
-export type UIElicitationFieldValue = string | number | boolean | string[];
+
export type PermissionDecision =
| {
/**
@@ -66,22 +125,523 @@ export type PermissionDecision =
}
| {
/**
- * Denied by a permission request hook registered by an extension or plugin
+ * Denied by a permission request hook registered by an extension or plugin
+ */
+ kind: "denied-by-permission-request-hook";
+ /**
+ * Optional message from the hook explaining the denial
+ */
+ message?: string;
+ /**
+ * Whether to interrupt the current agent turn
+ */
+ interrupt?: boolean;
+ };
+/**
+ * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info".
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "SessionLogLevel".
+ */
+export type SessionLogLevel = "info" | "warning" | "error";
+/**
+ * MCP server configuration (local/stdio or remote/http)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_McpServerConfig".
+ */
+export type $Defs_McpServerConfig =
+ | {
+ /**
+ * Tools to include. Defaults to all tools if not specified.
+ */
+ tools?: string[];
+ type?: "local" | "stdio";
+ isDefaultServer?: boolean;
+ filterMapping?: FilterMapping;
+ /**
+ * Timeout in milliseconds for tool calls to this server.
+ */
+ timeout?: number;
+ command: string;
+ args: string[];
+ cwd?: string;
+ env?: {
+ [k: string]: string;
+ };
+ }
+ | {
+ /**
+ * Tools to include. Defaults to all tools if not specified.
+ */
+ tools?: string[];
+ /**
+ * Remote transport type. Defaults to "http" when omitted.
+ */
+ type?: "http" | "sse";
+ isDefaultServer?: boolean;
+ filterMapping?: FilterMapping;
+ /**
+ * Timeout in milliseconds for tool calls to this server.
+ */
+ timeout?: number;
+ url: string;
+ headers?: {
+ [k: string]: string;
+ };
+ oauthClientId?: string;
+ oauthPublicClient?: boolean;
+ };
+
+export type $Defs_FilterMapping =
+ | {
+ [k: string]: "none" | "markdown" | "hidden_characters";
+ }
+ | ("none" | "markdown" | "hidden_characters");
+/**
+ * The agent mode. Valid values: "interactive", "plan", "autopilot".
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_SessionMode".
+ */
+export type $Defs_SessionMode = "interactive" | "plan" | "autopilot";
+/**
+ * The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_UIElicitationResponseAction".
+ */
+export type $Defs_UIElicitationResponseAction = "accept" | "decline" | "cancel";
+
+export type $Defs_UIElicitationFieldValue = string | number | boolean | string[];
+
+export type $Defs_PermissionDecision =
+ | {
+ /**
+ * The permission request was approved
+ */
+ kind: "approved";
+ }
+ | {
+ /**
+ * Denied because approval rules explicitly blocked it
+ */
+ kind: "denied-by-rules";
+ /**
+ * Rules that denied the request
+ */
+ rules: unknown[];
+ }
+ | {
+ /**
+ * Denied because no approval rule matched and user confirmation was unavailable
+ */
+ kind: "denied-no-approval-rule-and-could-not-request-from-user";
+ }
+ | {
+ /**
+ * Denied by the user during an interactive prompt
+ */
+ kind: "denied-interactively-by-user";
+ /**
+ * Optional feedback from the user explaining the denial
+ */
+ feedback?: string;
+ }
+ | {
+ /**
+ * Denied by the organization's content exclusion policy
+ */
+ kind: "denied-by-content-exclusion-policy";
+ /**
+ * File path that triggered the exclusion
+ */
+ path: string;
+ /**
+ * Human-readable explanation of why the path was excluded
+ */
+ message: string;
+ }
+ | {
+ /**
+ * Denied by a permission request hook registered by an extension or plugin
+ */
+ kind: "denied-by-permission-request-hook";
+ /**
+ * Optional message from the hook explaining the denial
+ */
+ message?: string;
+ /**
+ * Whether to interrupt the current agent turn
+ */
+ interrupt?: boolean;
+ };
+/**
+ * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info".
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_SessionLogLevel".
+ */
+export type $Defs_SessionLogLevel = "info" | "warning" | "error";
+
+/**
+ * Model capabilities and limits
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "ModelCapabilities".
+ */
+export interface ModelCapabilities {
+ /**
+ * Feature flags indicating what the model supports
+ */
+ supports?: {
+ /**
+ * Whether this model supports vision/image input
+ */
+ vision?: boolean;
+ /**
+ * Whether this model supports reasoning effort configuration
+ */
+ reasoningEffort?: boolean;
+ };
+ /**
+ * Token limits for prompts, outputs, and context window
+ */
+ limits?: {
+ /**
+ * Maximum number of prompt/input tokens
+ */
+ max_prompt_tokens?: number;
+ /**
+ * Maximum number of output/completion tokens
+ */
+ max_output_tokens?: number;
+ /**
+ * Maximum total context window size in tokens
+ */
+ max_context_window_tokens?: number;
+ vision?: ModelCapabilitiesLimitsVision;
+ };
+}
+/**
+ * Vision-specific limits
+ */
+export interface ModelCapabilitiesLimitsVision {
+ /**
+ * MIME types the model accepts
+ */
+ supported_media_types: string[];
+ /**
+ * Maximum number of images per prompt
+ */
+ max_prompt_images: number;
+ /**
+ * Maximum image size in bytes
+ */
+ max_prompt_image_size: number;
+}
+/**
+ * Vision-specific limits
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "ModelCapabilitiesLimitsVision".
+ */
+export interface ModelCapabilitiesLimitsVision1 {
+ /**
+ * MIME types the model accepts
+ */
+ supported_media_types: string[];
+ /**
+ * Maximum number of images per prompt
+ */
+ max_prompt_images: number;
+ /**
+ * Maximum image size in bytes
+ */
+ max_prompt_image_size: number;
+}
+
+export interface DiscoveredMcpServer {
+ /**
+ * Server name (config key)
+ */
+ name: string;
+ /**
+ * Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)
+ */
+ type?: "stdio" | "http" | "sse" | "memory";
+ /**
+ * Configuration source
+ */
+ source: "user" | "workspace" | "plugin" | "builtin";
+ /**
+ * Whether the server is enabled (not in the disabled list)
+ */
+ enabled: boolean;
+}
+
+export interface ServerSkillList {
+ /**
+ * All discovered skills across all sources
+ */
+ skills: ServerSkill[];
+}
+
+export interface ServerSkill {
+ /**
+ * Unique identifier for the skill
+ */
+ name: string;
+ /**
+ * Description of what the skill does
+ */
+ description: string;
+ /**
+ * Source location type (e.g., project, personal-copilot, plugin, builtin)
+ */
+ source: string;
+ /**
+ * 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;
+}
+
+export interface CurrentModel {
+ /**
+ * Currently active model identifier
+ */
+ modelId?: string;
+}
+/**
+ * Override individual model capabilities resolved by the runtime
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "ModelCapabilitiesOverride".
+ */
+export interface ModelCapabilitiesOverride {
+ /**
+ * Feature flags indicating what the model supports
+ */
+ supports?: {
+ vision?: boolean;
+ reasoningEffort?: boolean;
+ };
+ /**
+ * Token limits for prompts, outputs, and context window
+ */
+ limits?: {
+ max_prompt_tokens?: number;
+ max_output_tokens?: number;
+ /**
+ * Maximum total context window size in tokens
+ */
+ max_context_window_tokens?: number;
+ vision?: {
+ /**
+ * MIME types the model accepts
*/
- kind: "denied-by-permission-request-hook";
+ supported_media_types?: string[];
/**
- * Optional message from the hook explaining the denial
+ * Maximum number of images per prompt
*/
- message?: string;
+ max_prompt_images?: number;
/**
- * Whether to interrupt the current agent turn
+ * Maximum image size in bytes
*/
- interrupt?: boolean;
+ max_prompt_image_size?: number;
};
+ };
+}
+
+export interface AgentInfo {
+ /**
+ * Unique identifier of the custom agent
+ */
+ name: string;
+ /**
+ * Human-readable display name
+ */
+ displayName: string;
+ /**
+ * Description of the agent's purpose
+ */
+ description: string;
+}
+
+/** @experimental */
+export interface McpServerList {
+ /**
+ * Configured MCP servers
+ */
+ servers: {
+ /**
+ * Server name (config key)
+ */
+ name: string;
+ /**
+ * Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
+ */
+ status: "connected" | "failed" | "needs-auth" | "pending" | "disabled" | "not_configured";
+ /**
+ * Configuration source: user, workspace, plugin, or builtin
+ */
+ source?: "user" | "workspace" | "plugin" | "builtin";
+ /**
+ * Error message if the server failed to connect
+ */
+ error?: string;
+ }[];
+}
+
+export interface ToolCallResult {
+ /**
+ * Text result to send back to the LLM
+ */
+ textResultForLlm: string;
+ /**
+ * Type of the tool result
+ */
+ resultType?: string;
+ /**
+ * Error message if the tool call failed
+ */
+ error?: string;
+ /**
+ * Telemetry data from tool execution
+ */
+ toolTelemetry?: {
+ [k: string]: unknown;
+ };
+}
+
+export interface HandleToolCallResult {
+ /**
+ * Whether the tool call result was handled successfully
+ */
+ success: boolean;
+}
+
+export interface UIElicitationStringEnumField {
+ type: "string";
+ description?: string;
+ enum: string[];
+ enumNames?: string[];
+ default?: string;
+}
+
+export interface UIElicitationStringOneOfField {
+ type: "string";
+ description?: string;
+ oneOf: {
+ const: string;
+ }[];
+ default?: string;
+}
+
+export interface UIElicitationArrayEnumField {
+ type: "array";
+ description?: string;
+ minItems?: number;
+ maxItems?: number;
+ items: {
+ type: "string";
+ enum: string[];
+ };
+ default?: string[];
+}
+
+export interface UIElicitationArrayAnyOfField {
+ type: "array";
+ description?: string;
+ minItems?: number;
+ maxItems?: number;
+ items: {
+ anyOf: {
+ const: string;
+ }[];
+ };
+ default?: string[];
+}
/**
- * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info".
+ * The elicitation response (accept with form values, decline, or cancel)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "UIElicitationResponse".
*/
-export type SessionLogLevel = "info" | "warning" | "error";
+export interface UIElicitationResponse {
+ /**
+ * The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+ */
+ action: "accept" | "decline" | "cancel";
+ content?: UIElicitationResponseContent;
+}
+/**
+ * The form values submitted by the user (present when action is 'accept')
+ */
+export interface UIElicitationResponseContent {
+ [k: string]: UIElicitationFieldValue;
+}
+/**
+ * The form values submitted by the user (present when action is 'accept')
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "UIElicitationResponseContent".
+ */
+export interface UIElicitationResponseContent1 {
+ [k: string]: UIElicitationFieldValue;
+}
+
+export interface UIHandlePendingElicitationRequest {
+ /**
+ * The unique request ID from the elicitation.requested event
+ */
+ requestId: string;
+ result: UIElicitationResponse1;
+}
+/**
+ * The elicitation response (accept with form values, decline, or cancel)
+ */
+export interface UIElicitationResponse1 {
+ /**
+ * The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
+ */
+ action: "accept" | "decline" | "cancel";
+ content?: UIElicitationResponseContent;
+}
+
+export interface UIElicitationResult {
+ /**
+ * Whether the response was accepted. False if the request was already resolved by another client.
+ */
+ success: boolean;
+}
+
+export interface PermissionDecisionRequest {
+ /**
+ * Request ID of the pending permission request
+ */
+ requestId: string;
+ result: PermissionDecision;
+}
+
+export interface PermissionRequestResult {
+ /**
+ * Whether the permission request was handled successfully
+ */
+ success: boolean;
+}
export interface PingResult {
/**
@@ -118,7 +678,7 @@ export interface ModelList {
* Display name
*/
name: string;
- capabilities: ModelCapabilities;
+ capabilities: ModelCapabilities1;
/**
* Policy state (if applicable)
*/
@@ -154,7 +714,7 @@ export interface ModelList {
/**
* Model capabilities and limits
*/
-export interface ModelCapabilities {
+export interface ModelCapabilities1 {
/**
* Feature flags indicating what the model supports
*/
@@ -184,23 +744,7 @@ export interface ModelCapabilities {
* Maximum total context window size in tokens
*/
max_context_window_tokens?: number;
- /**
- * Vision-specific limits
- */
- vision?: {
- /**
- * MIME types the model accepts
- */
- supported_media_types: string[];
- /**
- * Maximum number of images per prompt
- */
- max_prompt_images: number;
- /**
- * Maximum image size in bytes
- */
- max_prompt_image_size: number;
- };
+ vision?: ModelCapabilitiesLimitsVision;
};
}
@@ -291,11 +835,7 @@ export interface McpConfigList {
tools?: string[];
type?: "local" | "stdio";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -317,11 +857,7 @@ export interface McpConfigList {
*/
type?: "http" | "sse";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -352,11 +888,7 @@ export interface McpConfigAddRequest {
tools?: string[];
type?: "local" | "stdio";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -378,11 +910,7 @@ export interface McpConfigAddRequest {
*/
type?: "http" | "sse";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -412,11 +940,7 @@ export interface McpConfigUpdateRequest {
tools?: string[];
type?: "local" | "stdio";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -438,11 +962,7 @@ export interface McpConfigUpdateRequest {
*/
type?: "http" | "sse";
isDefaultServer?: boolean;
- filterMapping?:
- | {
- [k: string]: "none" | "markdown" | "hidden_characters";
- }
- | ("none" | "markdown" | "hidden_characters");
+ filterMapping?: FilterMapping;
/**
* Timeout in milliseconds for tool calls to this server.
*/
@@ -465,78 +985,23 @@ export interface McpConfigRemoveRequest {
export interface McpDiscoverResult {
/**
- * MCP servers discovered from all sources
- */
- servers: DiscoveredMcpServer[];
-}
-export interface DiscoveredMcpServer {
- /**
- * Server name (config key)
- */
- name: string;
- /**
- * Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)
- */
- type?: "stdio" | "http" | "sse" | "memory";
- /**
- * Configuration source
- */
- source: "user" | "workspace" | "plugin" | "builtin";
- /**
- * Whether the server is enabled (not in the disabled list)
- */
- enabled: boolean;
-}
-
-export interface McpDiscoverRequest {
- /**
- * Working directory used as context for discovery (e.g., plugin resolution)
- */
- workingDirectory?: string;
-}
-
-export interface SkillsConfigSetDisabledSkillsRequest {
- /**
- * List of skill names to disable
- */
- disabledSkills: string[];
-}
-
-export interface ServerSkillList {
- /**
- * All discovered skills across all sources
- */
- skills: ServerSkill[];
-}
-export interface ServerSkill {
- /**
- * Unique identifier for the skill
- */
- name: string;
- /**
- * Description of what the skill does
- */
- description: string;
- /**
- * Source location type (e.g., project, personal-copilot, plugin, builtin)
- */
- source: string;
- /**
- * 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)
+ * MCP servers discovered from all sources
*/
- enabled: boolean;
+ servers: DiscoveredMcpServer[];
+}
+
+export interface McpDiscoverRequest {
/**
- * Absolute path to the skill file
+ * Working directory used as context for discovery (e.g., plugin resolution)
*/
- path?: string;
+ workingDirectory?: string;
+}
+
+export interface SkillsConfigSetDisabledSkillsRequest {
/**
- * The project path this skill belongs to (only for project/inherited skills)
+ * List of skill names to disable
*/
- projectPath?: string;
+ disabledSkills: string[];
}
export interface SkillsDiscoverRequest {
@@ -592,13 +1057,6 @@ export interface SessionsForkRequest {
toEventId?: string;
}
-export interface CurrentModel {
- /**
- * Currently active model identifier
- */
- modelId?: string;
-}
-
export interface ModelSwitchToResult {
/**
* Currently active model identifier after the switch
@@ -615,12 +1073,12 @@ export interface ModelSwitchToRequest {
* Reasoning effort level to use for the model
*/
reasoningEffort?: string;
- modelCapabilities?: ModelCapabilitiesOverride;
+ modelCapabilities?: ModelCapabilitiesOverride1;
}
/**
* Override individual model capabilities resolved by the runtime
*/
-export interface ModelCapabilitiesOverride {
+export interface ModelCapabilitiesOverride1 {
/**
* Feature flags indicating what the model supports
*/
@@ -656,7 +1114,10 @@ export interface ModelCapabilitiesOverride {
}
export interface ModeSetRequest {
- mode: SessionMode;
+ /**
+ * The agent mode. Valid values: "interactive", "plan", "autopilot".
+ */
+ mode: "interactive" | "plan" | "autopilot";
}
export interface NameGetResult {
@@ -752,6 +1213,46 @@ export interface WorkspacesCreateFileRequest {
content: string;
}
+export interface InstructionsGetSourcesResult {
+ /**
+ * Instruction sources for the session
+ */
+ sources: {
+ /**
+ * Unique identifier for this source (used for toggling)
+ */
+ id: string;
+ /**
+ * Human-readable label
+ */
+ label: string;
+ /**
+ * File path relative to repo or absolute for home
+ */
+ sourcePath: string;
+ /**
+ * Raw content of the instruction file
+ */
+ content: string;
+ /**
+ * Category of instruction source — used for merge logic
+ */
+ type: "home" | "repo" | "model" | "vscode" | "nested-agents" | "child-instructions";
+ /**
+ * Where this source lives — used for UI grouping
+ */
+ location: "user" | "repository" | "working-directory";
+ /**
+ * Glob pattern from frontmatter — when set, this instruction applies only to matching files
+ */
+ applyTo?: string;
+ /**
+ * Short description (body after frontmatter) for use in instruction tables
+ */
+ description?: string;
+ }[];
+}
+
/** @experimental */
export interface FleetStartResult {
/**
@@ -773,20 +1274,7 @@ export interface AgentList {
/**
* Available custom agents
*/
- agents: {
- /**
- * Unique identifier of the custom agent
- */
- name: string;
- /**
- * Human-readable display name
- */
- displayName: string;
- /**
- * Description of the agent's purpose
- */
- description: string;
- }[];
+ agents: AgentInfo[];
}
/** @experimental */
@@ -794,41 +1282,29 @@ export interface AgentGetCurrentResult {
/**
* Currently selected custom agent, or null if using the default agent
*/
- agent: {
- /**
- * Unique identifier of the custom agent
- */
- name: string;
- /**
- * Human-readable display name
- */
- displayName: string;
- /**
- * Description of the agent's purpose
- */
- description: string;
- } | null;
+ agent?: AgentInfo | null;
}
/** @experimental */
export interface AgentSelectResult {
+ agent: AgentInfo1;
+}
+/**
+ * The newly selected custom agent
+ */
+export interface AgentInfo1 {
/**
- * The newly selected custom agent
+ * Unique identifier of the custom agent
*/
- agent: {
- /**
- * Unique identifier of the custom agent
- */
- name: string;
- /**
- * Human-readable display name
- */
- displayName: string;
- /**
- * Description of the agent's purpose
- */
- description: string;
- };
+ name: string;
+ /**
+ * Human-readable display name
+ */
+ displayName: string;
+ /**
+ * Description of the agent's purpose
+ */
+ description: string;
}
/** @experimental */
@@ -844,20 +1320,7 @@ export interface AgentReloadResult {
/**
* Reloaded custom agents
*/
- agents: {
- /**
- * Unique identifier of the custom agent
- */
- name: string;
- /**
- * Human-readable display name
- */
- displayName: string;
- /**
- * Description of the agent's purpose
- */
- description: string;
- }[];
+ agents: AgentInfo[];
}
/** @experimental */
@@ -909,31 +1372,6 @@ export interface SkillsDisableRequest {
name: string;
}
-/** @experimental */
-export interface McpServerList {
- /**
- * Configured MCP servers
- */
- servers: {
- /**
- * Server name (config key)
- */
- name: string;
- /**
- * Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
- */
- status: "connected" | "failed" | "needs-auth" | "pending" | "disabled" | "not_configured";
- /**
- * Configuration source: user, workspace, plugin, or builtin
- */
- source?: "user" | "workspace" | "plugin" | "builtin";
- /**
- * Error message if the server failed to connect
- */
- error?: string;
- }[];
-}
-
/** @experimental */
export interface McpEnableRequest {
/**
@@ -1020,13 +1458,6 @@ export interface ExtensionsDisableRequest {
id: string;
}
-export interface HandleToolCallResult {
- /**
- * Whether the tool call result was handled successfully
- */
- success: boolean;
-}
-
export interface ToolsHandlePendingToolCallRequest {
/**
* Request ID of the pending tool call
@@ -1041,26 +1472,6 @@ export interface ToolsHandlePendingToolCallRequest {
*/
error?: string;
}
-export interface ToolCallResult {
- /**
- * Text result to send back to the LLM
- */
- textResultForLlm: string;
- /**
- * Type of the tool result
- */
- resultType?: string;
- /**
- * Error message if the tool call failed
- */
- error?: string;
- /**
- * Telemetry data from tool execution
- */
- toolTelemetry?: {
- [k: string]: unknown;
- };
-}
export interface CommandsHandlePendingCommandResult {
/**
@@ -1079,22 +1490,6 @@ export interface CommandsHandlePendingCommandRequest {
*/
error?: string;
}
-/**
- * The elicitation response (accept with form values, decline, or cancel)
- *
- * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
- * via the `definition` "UIElicitationResponse".
- */
-export interface UIElicitationResponse {
- action: UIElicitationResponseAction;
- content?: UIElicitationResponseContent;
-}
-/**
- * The form values submitted by the user (present when action is 'accept')
- */
-export interface UIElicitationResponseContent {
- [k: string]: UIElicitationFieldValue;
-}
export interface UIElicitationRequest {
/**
@@ -1116,102 +1511,34 @@ export interface UIElicitationRequest {
[k: string]:
| UIElicitationStringEnumField
| UIElicitationStringOneOfField
- | UIElicitationArrayEnumField
- | UIElicitationArrayAnyOfField
- | {
- type: "boolean";
- description?: string;
- default?: boolean;
- }
- | {
- type: "string";
- description?: string;
- minLength?: number;
- maxLength?: number;
- format?: "email" | "uri" | "date" | "date-time";
- default?: string;
- }
- | {
- type: "number" | "integer";
- description?: string;
- minimum?: number;
- maximum?: number;
- default?: number;
- };
- };
- /**
- * List of required field names
- */
- required?: string[];
- };
-}
-export interface UIElicitationStringEnumField {
- type: "string";
- description?: string;
- enum: string[];
- enumNames?: string[];
- default?: string;
-}
-export interface UIElicitationStringOneOfField {
- type: "string";
- description?: string;
- oneOf: {
- const: string;
- }[];
- default?: string;
-}
-export interface UIElicitationArrayEnumField {
- type: "array";
- description?: string;
- minItems?: number;
- maxItems?: number;
- items: {
- type: "string";
- enum: string[];
- };
- default?: string[];
-}
-export interface UIElicitationArrayAnyOfField {
- type: "array";
- description?: string;
- minItems?: number;
- maxItems?: number;
- items: {
- anyOf: {
- const: string;
- }[];
- };
- default?: string[];
-}
-
-export interface UIElicitationResult {
- /**
- * Whether the response was accepted. False if the request was already resolved by another client.
- */
- success: boolean;
-}
-
-export interface UIHandlePendingElicitationRequest {
- /**
- * The unique request ID from the elicitation.requested event
- */
- requestId: string;
- result: UIElicitationResponse;
-}
-
-export interface PermissionRequestResult {
- /**
- * Whether the permission request was handled successfully
- */
- success: boolean;
-}
-
-export interface PermissionDecisionRequest {
- /**
- * Request ID of the pending permission request
- */
- requestId: string;
- result: PermissionDecision;
+ | UIElicitationArrayEnumField
+ | UIElicitationArrayAnyOfField
+ | {
+ type: "boolean";
+ description?: string;
+ default?: boolean;
+ }
+ | {
+ type: "string";
+ description?: string;
+ minLength?: number;
+ maxLength?: number;
+ format?: "email" | "uri" | "date" | "date-time";
+ default?: string;
+ }
+ | {
+ type: "number" | "integer";
+ description?: string;
+ minimum?: number;
+ maximum?: number;
+ default?: number;
+ };
+ };
+ /**
+ * List of required field names
+ */
+ required?: string[];
+ };
}
export interface LogResult {
@@ -1226,7 +1553,10 @@ export interface LogRequest {
* Human-readable message
*/
message: string;
- level?: SessionLogLevel;
+ /**
+ * Log severity level. Determines how the message is displayed in the timeline. Defaults to "info".
+ */
+ level?: "info" | "warning" | "error";
/**
* When true, the message is transient and not persisted to the session event log on disk
*/
@@ -1466,176 +1796,533 @@ export interface SessionFsWriteFileRequest {
/**
* Optional POSIX-style mode for newly created files
*/
- mode?: number;
+ mode?: number;
+}
+
+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;
+}
+
+export interface SessionFsExistsResult {
+ /**
+ * Whether the path exists
+ */
+ exists: boolean;
+}
+
+export interface SessionFsExistsRequest {
+ /**
+ * Target session identifier
+ */
+ sessionId: string;
+ /**
+ * Path using SessionFs conventions
+ */
+ path: string;
+}
+
+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;
+}
+
+export interface SessionFsStatRequest {
+ /**
+ * Target session identifier
+ */
+ sessionId: string;
+ /**
+ * Path using SessionFs conventions
+ */
+ path: string;
+}
+
+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;
+}
+
+export interface SessionFsReaddirResult {
+ /**
+ * Entry names in the directory
+ */
+ entries: string[];
+}
+
+export interface SessionFsReaddirRequest {
+ /**
+ * Target session identifier
+ */
+ sessionId: string;
+ /**
+ * Path using SessionFs conventions
+ */
+ path: string;
+}
+
+export interface SessionFsReaddirWithTypesResult {
+ /**
+ * Directory entries with type information
+ */
+ entries: {
+ /**
+ * Entry name
+ */
+ name: string;
+ /**
+ * Entry type
+ */
+ type: "file" | "directory";
+ }[];
+}
+
+export interface SessionFsReaddirWithTypesRequest {
+ /**
+ * Target session identifier
+ */
+ sessionId: string;
+ /**
+ * Path using SessionFs conventions
+ */
+ path: string;
+}
+
+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;
+}
+
+export interface SessionFsRenameRequest {
+ /**
+ * Target session identifier
+ */
+ sessionId: string;
+ /**
+ * Source path using SessionFs conventions
+ */
+ src: string;
+ /**
+ * Destination path using SessionFs conventions
+ */
+ dest: string;
+}
+/**
+ * Model capabilities and limits
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_ModelCapabilities".
+ */
+export interface $Defs_ModelCapabilities {
+ /**
+ * Feature flags indicating what the model supports
+ */
+ supports?: {
+ /**
+ * Whether this model supports vision/image input
+ */
+ vision?: boolean;
+ /**
+ * Whether this model supports reasoning effort configuration
+ */
+ reasoningEffort?: boolean;
+ };
+ /**
+ * Token limits for prompts, outputs, and context window
+ */
+ limits?: {
+ /**
+ * Maximum number of prompt/input tokens
+ */
+ max_prompt_tokens?: number;
+ /**
+ * Maximum number of output/completion tokens
+ */
+ max_output_tokens?: number;
+ /**
+ * Maximum total context window size in tokens
+ */
+ max_context_window_tokens?: number;
+ vision?: ModelCapabilitiesLimitsVision2;
+ };
+}
+/**
+ * Vision-specific limits
+ */
+export interface ModelCapabilitiesLimitsVision2 {
+ /**
+ * 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;
+}
+/**
+ * Vision-specific limits
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_ModelCapabilitiesLimitsVision".
+ */
+export interface $Defs_ModelCapabilitiesLimitsVision {
+ /**
+ * MIME types the model accepts
+ */
+ supported_media_types: string[];
+ /**
+ * Maximum number of images per prompt
+ */
+ max_prompt_images: number;
+ /**
+ * Maximum image size in bytes
+ */
+ max_prompt_image_size: number;
}
-export interface SessionFsAppendFileRequest {
+export interface $Defs_DiscoveredMcpServer {
/**
- * Target session identifier
+ * Server name (config key)
*/
- sessionId: string;
+ name: string;
/**
- * Path using SessionFs conventions
+ * Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)
*/
- path: string;
+ type?: "stdio" | "http" | "sse" | "memory";
/**
- * Content to append
+ * Configuration source
*/
- content: string;
+ source: "user" | "workspace" | "plugin" | "builtin";
/**
- * Optional POSIX-style mode for newly created files
+ * Whether the server is enabled (not in the disabled list)
*/
- mode?: number;
+ enabled: boolean;
}
-export interface SessionFsExistsResult {
+export interface $Defs_ServerSkillList {
/**
- * Whether the path exists
+ * All discovered skills across all sources
*/
- exists: boolean;
+ skills: ServerSkill[];
}
-export interface SessionFsExistsRequest {
+export interface $Defs_ServerSkill {
/**
- * Target session identifier
+ * Unique identifier for the skill
*/
- sessionId: string;
+ name: string;
/**
- * Path using SessionFs conventions
+ * Description of what the skill does
*/
- path: string;
-}
-
-export interface SessionFsStatResult {
+ description: string;
/**
- * Whether the path is a file
+ * Source location type (e.g., project, personal-copilot, plugin, builtin)
*/
- isFile: boolean;
+ source: string;
/**
- * Whether the path is a directory
+ * Whether the skill can be invoked by the user as a slash command
*/
- isDirectory: boolean;
+ userInvocable: boolean;
/**
- * File size in bytes
+ * Whether the skill is currently enabled (based on global config)
*/
- size: number;
+ enabled: boolean;
/**
- * ISO 8601 timestamp of last modification
+ * Absolute path to the skill file
*/
- mtime: string;
+ path?: string;
/**
- * ISO 8601 timestamp of creation
+ * The project path this skill belongs to (only for project/inherited skills)
*/
- birthtime: string;
+ projectPath?: string;
}
-export interface SessionFsStatRequest {
+export interface $Defs_CurrentModel {
/**
- * Target session identifier
- */
- sessionId: string;
- /**
- * Path using SessionFs conventions
+ * Currently active model identifier
*/
- path: string;
+ modelId?: string;
}
-
-export interface SessionFsMkdirRequest {
- /**
- * Target session identifier
- */
- sessionId: string;
- /**
- * Path using SessionFs conventions
- */
- path: string;
+/**
+ * Override individual model capabilities resolved by the runtime
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_ModelCapabilitiesOverride".
+ */
+export interface $Defs_ModelCapabilitiesOverride {
/**
- * Create parent directories as needed
+ * Feature flags indicating what the model supports
*/
- recursive?: boolean;
+ supports?: {
+ vision?: boolean;
+ reasoningEffort?: boolean;
+ };
/**
- * Optional POSIX-style mode for newly created directories
+ * Token limits for prompts, outputs, and context window
*/
- mode?: number;
+ limits?: {
+ max_prompt_tokens?: number;
+ max_output_tokens?: number;
+ /**
+ * Maximum total context window size in tokens
+ */
+ max_context_window_tokens?: number;
+ vision?: {
+ /**
+ * MIME types the model accepts
+ */
+ supported_media_types?: string[];
+ /**
+ * Maximum number of images per prompt
+ */
+ max_prompt_images?: number;
+ /**
+ * Maximum image size in bytes
+ */
+ max_prompt_image_size?: number;
+ };
+ };
}
-export interface SessionFsReaddirResult {
+export interface $Defs_AgentInfo {
/**
- * Entry names in the directory
+ * Unique identifier of the custom agent
*/
- entries: string[];
-}
-
-export interface SessionFsReaddirRequest {
+ name: string;
/**
- * Target session identifier
+ * Human-readable display name
*/
- sessionId: string;
+ displayName: string;
/**
- * Path using SessionFs conventions
+ * Description of the agent's purpose
*/
- path: string;
+ description: string;
}
-export interface SessionFsReaddirWithTypesResult {
+export interface $Defs_McpServerList {
/**
- * Directory entries with type information
+ * Configured MCP servers
*/
- entries: {
+ servers: {
/**
- * Entry name
+ * Server name (config key)
*/
name: string;
/**
- * Entry type
+ * Connection status: connected, failed, needs-auth, pending, disabled, or not_configured
*/
- type: "file" | "directory";
+ status: "connected" | "failed" | "needs-auth" | "pending" | "disabled" | "not_configured";
+ /**
+ * Configuration source: user, workspace, plugin, or builtin
+ */
+ source?: "user" | "workspace" | "plugin" | "builtin";
+ /**
+ * Error message if the server failed to connect
+ */
+ error?: string;
}[];
}
-export interface SessionFsReaddirWithTypesRequest {
+export interface $Defs_ToolCallResult {
/**
- * Target session identifier
+ * Text result to send back to the LLM
*/
- sessionId: string;
+ textResultForLlm: string;
/**
- * Path using SessionFs conventions
+ * Type of the tool result
*/
- path: string;
+ resultType?: string;
+ /**
+ * Error message if the tool call failed
+ */
+ error?: string;
+ /**
+ * Telemetry data from tool execution
+ */
+ toolTelemetry?: {
+ [k: string]: unknown;
+ };
}
-export interface SessionFsRmRequest {
+export interface $Defs_HandleToolCallResult {
/**
- * Target session identifier
+ * Whether the tool call result was handled successfully
*/
- sessionId: string;
+ success: boolean;
+}
+
+export interface $Defs_UIElicitationStringEnumField {
+ type: "string";
+ description?: string;
+ enum: string[];
+ enumNames?: string[];
+ default?: string;
+}
+
+export interface $Defs_UIElicitationStringOneOfField {
+ type: "string";
+ description?: string;
+ oneOf: {
+ const: string;
+ }[];
+ default?: string;
+}
+
+export interface $Defs_UIElicitationArrayEnumField {
+ type: "array";
+ description?: string;
+ minItems?: number;
+ maxItems?: number;
+ items: {
+ type: "string";
+ enum: string[];
+ };
+ default?: string[];
+}
+
+export interface $Defs_UIElicitationArrayAnyOfField {
+ type: "array";
+ description?: string;
+ minItems?: number;
+ maxItems?: number;
+ items: {
+ anyOf: {
+ const: string;
+ }[];
+ };
+ default?: string[];
+}
+/**
+ * The elicitation response (accept with form values, decline, or cancel)
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_UIElicitationResponse".
+ */
+export interface $Defs_UIElicitationResponse {
/**
- * Path using SessionFs conventions
+ * The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
*/
- path: string;
+ action: "accept" | "decline" | "cancel";
+ content?: UIElicitationResponseContent2;
+}
+/**
+ * The form values submitted by the user (present when action is 'accept')
+ */
+export interface UIElicitationResponseContent2 {
+ [k: string]: UIElicitationFieldValue;
+}
+/**
+ * The form values submitted by the user (present when action is 'accept')
+ *
+ * This interface was referenced by `_RpcSchemaRoot`'s JSON-Schema
+ * via the `definition` "$defs_UIElicitationResponseContent".
+ */
+export interface $Defs_UIElicitationResponseContent {
+ [k: string]: UIElicitationFieldValue;
+}
+
+export interface $Defs_UIHandlePendingElicitationRequest {
/**
- * Remove directories and their contents recursively
+ * The unique request ID from the elicitation.requested event
*/
- recursive?: boolean;
+ requestId: string;
+ result: UIElicitationResponse2;
+}
+/**
+ * The elicitation response (accept with form values, decline, or cancel)
+ */
+export interface UIElicitationResponse2 {
/**
- * Ignore errors if the path does not exist
+ * The user's response: accept (submitted), decline (rejected), or cancel (dismissed)
*/
- force?: boolean;
+ action: "accept" | "decline" | "cancel";
+ content?: UIElicitationResponseContent;
}
-export interface SessionFsRenameRequest {
+export interface $Defs_UIElicitationResult {
/**
- * Target session identifier
+ * Whether the response was accepted. False if the request was already resolved by another client.
*/
- sessionId: string;
+ success: boolean;
+}
+
+export interface $Defs_PermissionDecisionRequest {
/**
- * Source path using SessionFs conventions
+ * Request ID of the pending permission request
*/
- src: string;
+ requestId: string;
+ result: PermissionDecision;
+}
+
+export interface $Defs_PermissionRequestResult {
/**
- * Destination path using SessionFs conventions
+ * Whether the permission request was handled successfully
*/
- dest: string;
+ success: boolean;
}
/** Create typed server-scoped RPC methods (no session required). */
@@ -1728,6 +2415,10 @@ export function createSessionRpc(connection: MessageConnection, sessionId: strin
createFile: async (params: Omit): Promise =>
connection.sendRequest("session.workspaces.createFile", { sessionId, ...params }),
},
+ instructions: {
+ getSources: async (): Promise =>
+ connection.sendRequest("session.instructions.getSources", { sessionId }),
+ },
/** @experimental */
fleet: {
start: async (params: Omit): Promise =>
diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts
index 65deaf2b3..d2de8d250 100644
--- a/nodejs/src/generated/session-events.ts
+++ b/nodejs/src/generated/session-events.ts
@@ -21,6 +21,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.start";
/**
* Session initialization metadata including context and configuration
@@ -54,39 +58,7 @@ export type SessionEvent =
* Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh")
*/
reasoningEffort?: string;
- /**
- * Working directory and git context at session start
- */
- context?: {
- /**
- * Current working directory path
- */
- cwd: string;
- /**
- * Root directory of the git repository, resolved via git rev-parse
- */
- gitRoot?: string;
- /**
- * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
- */
- repository?: string;
- /**
- * Hosting platform type of the repository (github or ado)
- */
- hostType?: "github" | "ado";
- /**
- * Current git branch name
- */
- branch?: string;
- /**
- * Head commit of current git branch at session start time
- */
- headCommit?: string;
- /**
- * Base commit of current git branch at session start time
- */
- baseCommit?: string;
- };
+ context?: WorkingDirectoryContext;
/**
* Whether the session was already in use by another client at start time
*/
@@ -114,6 +86,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.resume";
/**
* Session resume metadata including current context and event count
@@ -135,39 +111,7 @@ export type SessionEvent =
* Reasoning effort level used for model calls, if applicable (e.g. "low", "medium", "high", "xhigh")
*/
reasoningEffort?: string;
- /**
- * Updated working directory and git context at resume time
- */
- context?: {
- /**
- * Current working directory path
- */
- cwd: string;
- /**
- * Root directory of the git repository, resolved via git rev-parse
- */
- gitRoot?: string;
- /**
- * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
- */
- repository?: string;
- /**
- * Hosting platform type of the repository (github or ado)
- */
- hostType?: "github" | "ado";
- /**
- * Current git branch name
- */
- branch?: string;
- /**
- * Head commit of current git branch at session start time
- */
- headCommit?: string;
- /**
- * Base commit of current git branch at session start time
- */
- baseCommit?: string;
- };
+ context?: WorkingDirectoryContext1;
/**
* Whether the session was already in use by another client at resume time
*/
@@ -195,6 +139,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.remote_steerable_changed";
/**
* Notifies Mission Control that the session's remote steering capability has changed
@@ -223,6 +171,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.error";
/**
* Error details for timeline display including message and optional diagnostic information
@@ -268,6 +220,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.idle";
/**
* Payload indicating the session is idle with no background agents in flight
@@ -293,6 +249,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.title_changed";
/**
* Session title change payload containing the new display title
@@ -316,6 +276,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.info";
/**
* Informational message for timeline display with categorization
@@ -352,6 +316,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.warning";
/**
* Warning message for timeline display with categorization
@@ -388,6 +356,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.model_change";
/**
* Model change details including previous and new model identifiers
@@ -428,6 +400,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.mode_changed";
/**
* Agent mode change details including previous and new modes
@@ -460,6 +436,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.plan_changed";
/**
* Plan file operation details indicating what changed
@@ -488,6 +468,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.workspace_file_changed";
/**
* Workspace file change details including path and operation type
@@ -520,6 +504,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.handoff";
/**
* Session handoff metadata including source, context, and repository information
@@ -585,6 +573,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.truncation";
/**
* Conversation truncation statistics including token counts and removed content metrics
@@ -638,6 +630,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.snapshot_rewind";
/**
* Session rewind details including target event and count of removed events
@@ -670,6 +666,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.shutdown";
/**
* Session termination metrics including usage statistics, code changes, and shutdown reason
@@ -796,40 +796,12 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
- type: "session.context_changed";
/**
- * Updated working directory and git context after the change
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
*/
- data: {
- /**
- * Current working directory path
- */
- cwd: string;
- /**
- * Root directory of the git repository, resolved via git rev-parse
- */
- gitRoot?: string;
- /**
- * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
- */
- repository?: string;
- /**
- * Hosting platform type of the repository (github or ado)
- */
- hostType?: "github" | "ado";
- /**
- * Current git branch name
- */
- branch?: string;
- /**
- * Head commit of current git branch at session start time
- */
- headCommit?: string;
- /**
- * Base commit of current git branch at session start time
- */
- baseCommit?: string;
- };
+ agentId?: string;
+ type: "session.context_changed";
+ data: WorkingDirectoryContext2;
}
| {
/**
@@ -845,6 +817,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.usage_info";
/**
* Current context window usage statistics including token and message counts
@@ -897,6 +873,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.compaction_start";
/**
* Context window breakdown at the start of LLM-powered conversation compaction
@@ -933,6 +913,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.compaction_complete";
/**
* Conversation compaction results including success status, metrics, and optional error details
@@ -1030,6 +1014,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.task_complete";
/**
* Task completion notification with summary from the agent
@@ -1062,6 +1050,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "user.message";
data: {
/**
@@ -1207,6 +1199,14 @@ export type SessionEvent =
displayName?: string;
}
)[];
+ /**
+ * Normalized document MIME types that were sent natively instead of through tagged_files XML
+ */
+ supportedNativeDocumentMimeTypes?: string[];
+ /**
+ * Path-backed native document attachments that stayed on the tagged_files path flow because native upload would exceed the request size limit
+ */
+ nativeDocumentPathFallbackPaths?: string[];
/**
* Origin of this message, used for timeline filtering (e.g., "skill-pdf" for skill-injected messages that should be hidden from the user)
*/
@@ -1235,6 +1235,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "pending_messages.modified";
/**
* Empty payload; the event signals that the pending message queue has changed
@@ -1258,6 +1262,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.turn_start";
/**
* Turn initialization metadata including identifier and interaction tracking
@@ -1287,6 +1295,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.intent";
/**
* Agent intent description for current activity or plan
@@ -1315,6 +1327,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.reasoning";
/**
* Assistant reasoning content for timeline display with complete thinking text
@@ -1344,6 +1360,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.reasoning_delta";
/**
* Streaming reasoning delta for incremental extended thinking updates
@@ -1373,6 +1393,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.streaming_delta";
/**
* Streaming response progress with cumulative byte count
@@ -1401,6 +1425,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.message";
/**
* Assistant response containing text content, optional tool requests, and interaction metadata
@@ -1478,6 +1506,7 @@ export type SessionEvent =
*/
requestId?: string;
/**
+ * @deprecated
* Tool call ID of the parent tool invocation when this event originates from a sub-agent
*/
parentToolCallId?: string;
@@ -1497,6 +1526,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.message_delta";
/**
* Streaming assistant message delta for incremental response updates
@@ -1511,6 +1544,7 @@ export type SessionEvent =
*/
deltaContent: string;
/**
+ * @deprecated
* Tool call ID of the parent tool invocation when this event originates from a sub-agent
*/
parentToolCallId?: string;
@@ -1533,6 +1567,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.turn_end";
/**
* Turn completion metadata including the turn identifier
@@ -1558,6 +1596,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "assistant.usage";
/**
* LLM API call usage metrics including tokens, costs, quotas, and billing information
@@ -1616,6 +1658,7 @@ export type SessionEvent =
*/
providerCallId?: string;
/**
+ * @deprecated
* Parent tool call ID when this usage originates from a sub-agent
*/
parentToolCallId?: string;
@@ -1711,6 +1754,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "abort";
/**
* Turn abort information including the reason for termination
@@ -1739,6 +1786,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "tool.user_requested";
/**
* User-initiated tool invocation request with tool name and arguments
@@ -1777,6 +1828,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "tool.execution_start";
/**
* Tool execution startup details including MCP server information when applicable
@@ -1805,6 +1860,7 @@ export type SessionEvent =
*/
mcpToolName?: string;
/**
+ * @deprecated
* Tool call ID of the parent tool invocation when this event originates from a sub-agent
*/
parentToolCallId?: string;
@@ -1824,6 +1880,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "tool.execution_partial_result";
/**
* Streaming tool execution output for incremental result display
@@ -1853,6 +1913,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "tool.execution_progress";
/**
* Tool execution progress notification with status message
@@ -1885,6 +1949,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "tool.execution_complete";
/**
* Tool execution completion results including success status, detailed output, and error information
@@ -2061,6 +2129,7 @@ export type SessionEvent =
[k: string]: unknown;
};
/**
+ * @deprecated
* Tool call ID of the parent tool invocation when this event originates from a sub-agent
*/
parentToolCallId?: string;
@@ -2083,6 +2152,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "skill.invoked";
/**
* Skill invocation details including content, allowed tools, and plugin metadata
@@ -2135,6 +2208,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "subagent.started";
/**
* Sub-agent startup details including parent tool call and agent information
@@ -2175,6 +2252,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "subagent.completed";
/**
* Sub-agent completion details for successful execution
@@ -2227,6 +2308,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "subagent.failed";
/**
* Sub-agent failure details including error message and agent information
@@ -2283,6 +2368,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "subagent.selected";
/**
* Custom agent selection details including name and available tools
@@ -2319,6 +2408,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "subagent.deselected";
/**
* Empty payload; the event signals that the custom agent was deselected, returning to the default agent
@@ -2342,6 +2435,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "hook.start";
/**
* Hook invocation start details including type and input data
@@ -2380,6 +2477,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "hook.end";
/**
* Hook invocation completion details including output, success status, and error information
@@ -2435,13 +2536,17 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "system.message";
/**
- * System or developer message content with role and optional template metadata
+ * System/developer instruction content with role and optional template metadata
*/
data: {
/**
- * The system or developer prompt text
+ * The system or developer prompt text sent as model input
*/
content: string;
/**
@@ -2486,6 +2591,10 @@ export type SessionEvent =
* When true, the event is transient and not persisted to the session event log on disk
*/
ephemeral?: boolean;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "system.notification";
/**
* System-generated notification for runtime events like background task completion
@@ -2579,6 +2688,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "permission.requested";
/**
* Permission request notification requiring client approval with request details
@@ -2848,6 +2961,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "permission.completed";
/**
* Permission request completion notification signaling UI dismissal
@@ -2888,6 +3005,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "user_input.requested";
/**
* User input request notification with question and optional predefined choices
@@ -2929,6 +3050,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "user_input.completed";
/**
* User input request completion with the user's response
@@ -2962,6 +3087,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "elicitation.requested";
/**
* Elicitation request; may be form-based (structured input) or URL-based (browser redirect)
@@ -3027,6 +3156,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "elicitation.completed";
/**
* Elicitation request completion with the user's response
@@ -3062,6 +3195,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "sampling.requested";
/**
* Sampling request from an MCP server; contains the server name and a requestId for correlation
@@ -3096,6 +3233,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "sampling.completed";
/**
* Sampling request completion notification signaling UI dismissal
@@ -3121,6 +3262,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "mcp.oauth_required";
/**
* OAuth authentication request for an MCP server
@@ -3167,6 +3312,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "mcp.oauth_completed";
/**
* MCP OAuth request completion notification
@@ -3192,6 +3341,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "external_tool.requested";
/**
* External tool invocation request for client-side tool execution
@@ -3243,6 +3396,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "external_tool.completed";
/**
* External tool completion notification signaling UI dismissal
@@ -3268,6 +3425,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "command.queued";
/**
* Queued slash command dispatch request for client execution
@@ -3297,6 +3458,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "command.execute";
/**
* Registered command dispatch request routed to the owning client
@@ -3334,6 +3499,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "command.completed";
/**
* Queued command completion notification signaling UI dismissal
@@ -3359,6 +3528,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "commands.changed";
/**
* SDK command registration change notification
@@ -3387,6 +3560,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "capabilities.changed";
/**
* Session capability change notification
@@ -3417,6 +3594,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "exit_plan_mode.requested";
/**
* Plan approval request with plan content and available user actions
@@ -3458,6 +3639,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "exit_plan_mode.completed";
/**
* Plan mode exit completion with the user's approval decision and optional feedback
@@ -3499,6 +3684,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.tools_updated";
data: {
model: string;
@@ -3518,6 +3707,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.background_tasks_changed";
data: {};
}
@@ -3535,6 +3728,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.skills_loaded";
data: {
/**
@@ -3582,6 +3779,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.custom_agents_updated";
data: {
/**
@@ -3645,6 +3846,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.mcp_servers_loaded";
data: {
/**
@@ -3684,6 +3889,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.mcp_server_status_changed";
data: {
/**
@@ -3710,6 +3919,10 @@ export type SessionEvent =
*/
parentId: string | null;
ephemeral: true;
+ /**
+ * Sub-agent instance identifier. Absent for events from the root/main agent and session-level events.
+ */
+ agentId?: string;
type: "session.extensions_loaded";
data: {
/**
@@ -3736,6 +3949,105 @@ export type SessionEvent =
};
};
+/**
+ * Working directory and git context at session start
+ */
+export interface WorkingDirectoryContext {
+ /**
+ * Current working directory path
+ */
+ cwd: string;
+ /**
+ * Root directory of the git repository, resolved via git rev-parse
+ */
+ gitRoot?: string;
+ /**
+ * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
+ */
+ repository?: string;
+ /**
+ * Hosting platform type of the repository (github or ado)
+ */
+ hostType?: "github" | "ado";
+ /**
+ * Current git branch name
+ */
+ branch?: string;
+ /**
+ * Head commit of current git branch at session start time
+ */
+ headCommit?: string;
+ /**
+ * Base commit of current git branch at session start time
+ */
+ baseCommit?: string;
+}
+/**
+ * Updated working directory and git context at resume time
+ */
+export interface WorkingDirectoryContext1 {
+ /**
+ * Current working directory path
+ */
+ cwd: string;
+ /**
+ * Root directory of the git repository, resolved via git rev-parse
+ */
+ gitRoot?: string;
+ /**
+ * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
+ */
+ repository?: string;
+ /**
+ * Hosting platform type of the repository (github or ado)
+ */
+ hostType?: "github" | "ado";
+ /**
+ * Current git branch name
+ */
+ branch?: string;
+ /**
+ * Head commit of current git branch at session start time
+ */
+ headCommit?: string;
+ /**
+ * Base commit of current git branch at session start time
+ */
+ baseCommit?: string;
+}
+/**
+ * Updated working directory and git context after the change
+ */
+export interface WorkingDirectoryContext2 {
+ /**
+ * Current working directory path
+ */
+ cwd: string;
+ /**
+ * Root directory of the git repository, resolved via git rev-parse
+ */
+ gitRoot?: string;
+ /**
+ * Repository identifier derived from the git remote URL ("owner/name" for GitHub, "org/project/repo" for Azure DevOps)
+ */
+ repository?: string;
+ /**
+ * Hosting platform type of the repository (github or ado)
+ */
+ hostType?: "github" | "ado";
+ /**
+ * Current git branch name
+ */
+ branch?: string;
+ /**
+ * Head commit of current git branch at session start time
+ */
+ headCommit?: string;
+ /**
+ * Base commit of current git branch at session start time
+ */
+ baseCommit?: string;
+}
export interface EmbeddedTextResourceContents {
/**
* URI identifying the resource
diff --git a/python/copilot/generated/rpc.py b/python/copilot/generated/rpc.py
index c99182b17..1aa658823 100644
--- a/python/copilot/generated/rpc.py
+++ b/python/copilot/generated/rpc.py
@@ -21,14 +21,18 @@
EnumT = TypeVar("EnumT", bound=Enum)
-def from_str(x: Any) -> str:
- assert isinstance(x, str)
- return x
-
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x
+def from_list(f: Callable[[Any], T], x: Any) -> list[T]:
+ assert isinstance(x, list)
+ return [f(y) for y in x]
+
+def from_str(x: Any) -> str:
+ assert isinstance(x, str)
+ return x
+
def from_none(x: Any) -> Any:
assert x is None
return x
@@ -41,18 +45,6 @@ def from_union(fs, x):
pass
assert False
-def from_float(x: Any) -> float:
- assert isinstance(x, (float, int)) and not isinstance(x, bool)
- return float(x)
-
-def to_float(x: Any) -> float:
- assert isinstance(x, (int, float))
- return x
-
-def from_list(f: Callable[[Any], T], x: Any) -> list[T]:
- assert isinstance(x, list)
- return [f(y) for y in x]
-
def to_class(c: type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
@@ -65,76 +57,23 @@ def from_dict(f: Callable[[Any], T], x: Any) -> dict[str, T]:
assert isinstance(x, dict)
return { k: f(v) for (k, v) in x.items() }
-def from_datetime(x: Any) -> datetime:
- return dateutil.parser.parse(x)
-
def to_enum(c: type[EnumT], x: Any) -> EnumT:
assert isinstance(x, c)
return x.value
-@dataclass
-class PingResult:
- message: str
- """Echoed message (or default greeting)"""
-
- protocol_version: int
- """Server protocol version number"""
-
- timestamp: int
- """Server timestamp in milliseconds"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'PingResult':
- assert isinstance(obj, dict)
- message = from_str(obj.get("message"))
- protocol_version = from_int(obj.get("protocolVersion"))
- timestamp = from_int(obj.get("timestamp"))
- return PingResult(message, protocol_version, timestamp)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["message"] = from_str(self.message)
- result["protocolVersion"] = from_int(self.protocol_version)
- result["timestamp"] = from_int(self.timestamp)
- return result
-
-@dataclass
-class PingRequest:
- message: str | None = None
- """Optional message to echo back"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'PingRequest':
- assert isinstance(obj, dict)
- message = from_union([from_str, from_none], obj.get("message"))
- return PingRequest(message)
-
- def to_dict(self) -> dict:
- result: dict = {}
- if self.message is not None:
- result["message"] = from_union([from_str, from_none], self.message)
- return result
-
-@dataclass
-class ModelBilling:
- """Billing information"""
-
- multiplier: float
- """Billing cost multiplier relative to the base rate"""
+def from_float(x: Any) -> float:
+ assert isinstance(x, (float, int)) and not isinstance(x, bool)
+ return float(x)
- @staticmethod
- def from_dict(obj: Any) -> 'ModelBilling':
- assert isinstance(obj, dict)
- multiplier = from_float(obj.get("multiplier"))
- return ModelBilling(multiplier)
+def to_float(x: Any) -> float:
+ assert isinstance(x, (int, float))
+ return x
- def to_dict(self) -> dict:
- result: dict = {}
- result["multiplier"] = to_float(self.multiplier)
- return result
+def from_datetime(x: Any) -> datetime:
+ return dateutil.parser.parse(x)
@dataclass
-class ModelCapabilitiesLimitsVision:
+class PurpleModelCapabilitiesLimitsVision:
"""Vision-specific limits"""
max_prompt_image_size: int
@@ -147,12 +86,12 @@ class ModelCapabilitiesLimitsVision:
"""MIME types the model accepts"""
@staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilitiesLimitsVision':
+ def from_dict(obj: Any) -> 'PurpleModelCapabilitiesLimitsVision':
assert isinstance(obj, dict)
max_prompt_image_size = from_int(obj.get("max_prompt_image_size"))
max_prompt_images = from_int(obj.get("max_prompt_images"))
supported_media_types = from_list(from_str, obj.get("supported_media_types"))
- return ModelCapabilitiesLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
+ return PurpleModelCapabilitiesLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
def to_dict(self) -> dict:
result: dict = {}
@@ -161,43 +100,6 @@ def to_dict(self) -> dict:
result["supported_media_types"] = from_list(from_str, self.supported_media_types)
return result
-@dataclass
-class ModelCapabilitiesLimits:
- """Token limits for prompts, outputs, and context window"""
-
- 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 ModelCapabilitiesSupports:
"""Feature flags indicating what the model supports"""
@@ -224,716 +126,690 @@ def to_dict(self) -> dict:
return result
@dataclass
-class ModelCapabilities:
- """Model capabilities and limits"""
+class ModelCapabilitiesLimitsVision:
+ """Vision-specific limits"""
- limits: ModelCapabilitiesLimits | None = None
- """Token limits for prompts, outputs, and context window"""
+ max_prompt_image_size: int
+ """Maximum image size in bytes"""
- supports: ModelCapabilitiesSupports | None = None
- """Feature flags indicating what the model supports"""
+ max_prompt_images: int
+ """Maximum number of images per prompt"""
+
+ supported_media_types: list[str]
+ """MIME types the model accepts"""
@staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilities':
+ def from_dict(obj: Any) -> 'ModelCapabilitiesLimitsVision':
assert isinstance(obj, dict)
- limits = from_union([ModelCapabilitiesLimits.from_dict, from_none], obj.get("limits"))
- supports = from_union([ModelCapabilitiesSupports.from_dict, from_none], obj.get("supports"))
- return ModelCapabilities(limits, supports)
+ max_prompt_image_size = from_int(obj.get("max_prompt_image_size"))
+ max_prompt_images = from_int(obj.get("max_prompt_images"))
+ supported_media_types = from_list(from_str, obj.get("supported_media_types"))
+ return ModelCapabilitiesLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
def to_dict(self) -> dict:
result: dict = {}
- if self.limits is not None:
- result["limits"] = from_union([lambda x: to_class(ModelCapabilitiesLimits, x), from_none], self.limits)
- if self.supports is not None:
- result["supports"] = from_union([lambda x: to_class(ModelCapabilitiesSupports, x), from_none], self.supports)
+ result["max_prompt_image_size"] = from_int(self.max_prompt_image_size)
+ result["max_prompt_images"] = from_int(self.max_prompt_images)
+ result["supported_media_types"] = from_list(from_str, self.supported_media_types)
return result
-@dataclass
-class ModelPolicy:
- """Policy state (if applicable)"""
+class FilterMappingString(Enum):
+ HIDDEN_CHARACTERS = "hidden_characters"
+ MARKDOWN = "markdown"
+ NONE = "none"
- state: str
- """Current policy state for this model"""
+class MCPServerConfigType(Enum):
+ """Remote transport type. Defaults to "http" when omitted."""
- terms: str
- """Usage terms or conditions for this model"""
+ HTTP = "http"
+ LOCAL = "local"
+ SSE = "sse"
+ STDIO = "stdio"
- @staticmethod
- def from_dict(obj: Any) -> 'ModelPolicy':
- assert isinstance(obj, dict)
- state = from_str(obj.get("state"))
- terms = from_str(obj.get("terms"))
- return ModelPolicy(state, terms)
+class MCPServerSource(Enum):
+ """Configuration source
- def to_dict(self) -> dict:
- result: dict = {}
- result["state"] = from_str(self.state)
- result["terms"] = from_str(self.terms)
- return result
+ Configuration source: user, workspace, plugin, or builtin
+ """
+ BUILTIN = "builtin"
+ PLUGIN = "plugin"
+ USER = "user"
+ WORKSPACE = "workspace"
+
+class DiscoveredMCPServerType(Enum):
+ """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)"""
+
+ HTTP = "http"
+ MEMORY = "memory"
+ SSE = "sse"
+ STDIO = "stdio"
@dataclass
-class Model:
- capabilities: ModelCapabilities
- """Model capabilities and limits"""
+class SkillElement:
+ description: str
+ """Description of what the skill does"""
- id: str
- """Model identifier (e.g., "claude-sonnet-4.5")"""
+ enabled: bool
+ """Whether the skill is currently enabled (based on global config)"""
name: str
- """Display name"""
+ """Unique identifier for the skill"""
- billing: ModelBilling | None = None
- """Billing information"""
+ source: str
+ """Source location type (e.g., project, personal-copilot, plugin, builtin)"""
- default_reasoning_effort: str | None = None
- """Default reasoning effort level (only present if model supports reasoning effort)"""
+ user_invocable: bool
+ """Whether the skill can be invoked by the user as a slash command"""
- policy: ModelPolicy | None = None
- """Policy state (if applicable)"""
+ path: str | None = None
+ """Absolute path to the skill file"""
- supported_reasoning_efforts: list[str] | None = None
- """Supported reasoning effort levels (only present if model supports reasoning effort)"""
+ project_path: str | None = None
+ """The project path this skill belongs to (only for project/inherited skills)"""
@staticmethod
- def from_dict(obj: Any) -> 'Model':
+ def from_dict(obj: Any) -> 'SkillElement':
assert isinstance(obj, dict)
- capabilities = ModelCapabilities.from_dict(obj.get("capabilities"))
- id = from_str(obj.get("id"))
+ description = from_str(obj.get("description"))
+ enabled = from_bool(obj.get("enabled"))
name = from_str(obj.get("name"))
- billing = from_union([ModelBilling.from_dict, from_none], obj.get("billing"))
- default_reasoning_effort = from_union([from_str, from_none], obj.get("defaultReasoningEffort"))
- policy = from_union([ModelPolicy.from_dict, from_none], obj.get("policy"))
- supported_reasoning_efforts = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supportedReasoningEfforts"))
- return Model(capabilities, id, name, billing, default_reasoning_effort, policy, supported_reasoning_efforts)
+ source = from_str(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 SkillElement(description, enabled, name, source, user_invocable, path, project_path)
def to_dict(self) -> dict:
result: dict = {}
- result["capabilities"] = to_class(ModelCapabilities, self.capabilities)
- result["id"] = from_str(self.id)
+ result["description"] = from_str(self.description)
+ result["enabled"] = from_bool(self.enabled)
result["name"] = from_str(self.name)
- if self.billing is not None:
- result["billing"] = from_union([lambda x: to_class(ModelBilling, x), from_none], self.billing)
- if self.default_reasoning_effort is not None:
- result["defaultReasoningEffort"] = from_union([from_str, from_none], self.default_reasoning_effort)
- if self.policy is not None:
- result["policy"] = from_union([lambda x: to_class(ModelPolicy, x), from_none], self.policy)
- if self.supported_reasoning_efforts is not None:
- result["supportedReasoningEfforts"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_reasoning_efforts)
- return result
-
-@dataclass
-class ModelList:
- models: list[Model]
- """List of available models with full metadata"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModelList':
- assert isinstance(obj, dict)
- models = from_list(Model.from_dict, obj.get("models"))
- return ModelList(models)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["models"] = from_list(lambda x: to_class(Model, x), self.models)
+ result["source"] = from_str(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 Tool:
+class ServerSkill:
description: str
- """Description of what the tool does"""
+ """Description of what the skill does"""
+
+ enabled: bool
+ """Whether the skill is currently enabled (based on global config)"""
name: str
- """Tool identifier (e.g., "bash", "grep", "str_replace_editor")"""
+ """Unique identifier for the skill"""
- instructions: str | None = None
- """Optional instructions for how to use this tool effectively"""
+ source: str
+ """Source location type (e.g., project, personal-copilot, plugin, builtin)"""
- 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"""
+ 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) -> 'Tool':
+ def from_dict(obj: Any) -> 'ServerSkill':
assert isinstance(obj, dict)
description = from_str(obj.get("description"))
+ enabled = from_bool(obj.get("enabled"))
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)
+ source = from_str(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["description"] = from_str(self.description)
+ result["enabled"] = from_bool(self.enabled)
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["source"] = from_str(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 ToolList:
- tools: list[Tool]
- """List of available built-in tools with metadata"""
+class CurrentModel:
+ model_id: str | None = None
+ """Currently active model identifier"""
@staticmethod
- def from_dict(obj: Any) -> 'ToolList':
+ def from_dict(obj: Any) -> 'CurrentModel':
assert isinstance(obj, dict)
- tools = from_list(Tool.from_dict, obj.get("tools"))
- return ToolList(tools)
+ model_id = from_union([from_str, from_none], obj.get("modelId"))
+ return CurrentModel(model_id)
def to_dict(self) -> dict:
result: dict = {}
- result["tools"] = from_list(lambda x: to_class(Tool, x), self.tools)
+ if self.model_id is not None:
+ result["modelId"] = from_union([from_str, from_none], self.model_id)
return result
@dataclass
-class ToolsListRequest:
- model: str | None = None
- """Optional model ID — when provided, the returned tool list reflects model-specific
- overrides
- """
+class PurpleModelCapabilitiesOverrideLimitsVision:
+ max_prompt_image_size: int | None = None
+ """Maximum image size in bytes"""
+
+ max_prompt_images: int | None = None
+ """Maximum number of images per prompt"""
+
+ supported_media_types: list[str] | None = None
+ """MIME types the model accepts"""
@staticmethod
- def from_dict(obj: Any) -> 'ToolsListRequest':
+ def from_dict(obj: Any) -> 'PurpleModelCapabilitiesOverrideLimitsVision':
assert isinstance(obj, dict)
- model = from_union([from_str, from_none], obj.get("model"))
- return ToolsListRequest(model)
+ max_prompt_image_size = from_union([from_int, from_none], obj.get("max_prompt_image_size"))
+ max_prompt_images = from_union([from_int, from_none], obj.get("max_prompt_images"))
+ supported_media_types = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supported_media_types"))
+ return PurpleModelCapabilitiesOverrideLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
def to_dict(self) -> dict:
result: dict = {}
- if self.model is not None:
- result["model"] = from_union([from_str, from_none], self.model)
+ if self.max_prompt_image_size is not None:
+ result["max_prompt_image_size"] = from_union([from_int, from_none], self.max_prompt_image_size)
+ if self.max_prompt_images is not None:
+ result["max_prompt_images"] = from_union([from_int, from_none], self.max_prompt_images)
+ if self.supported_media_types is not None:
+ result["supported_media_types"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_media_types)
return result
@dataclass
-class AccountQuotaSnapshot:
- entitlement_requests: int
- """Number of requests included in the entitlement"""
-
- overage: int
- """Number of overage requests made this period"""
-
- overage_allowed_with_exhausted_quota: bool
- """Whether pay-per-request usage is allowed when quota is exhausted"""
-
- remaining_percentage: float
- """Percentage of entitlement remaining"""
-
- used_requests: int
- """Number of requests used so far this period"""
+class ModelCapabilitiesOverrideSupports:
+ """Feature flags indicating what the model supports"""
- reset_date: datetime | None = None
- """Date when the quota resets (ISO 8601)"""
+ reasoning_effort: bool | None = None
+ vision: bool | None = None
@staticmethod
- def from_dict(obj: Any) -> 'AccountQuotaSnapshot':
+ def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideSupports':
assert isinstance(obj, dict)
- entitlement_requests = from_int(obj.get("entitlementRequests"))
- overage = from_int(obj.get("overage"))
- overage_allowed_with_exhausted_quota = from_bool(obj.get("overageAllowedWithExhaustedQuota"))
- remaining_percentage = from_float(obj.get("remainingPercentage"))
- used_requests = from_int(obj.get("usedRequests"))
- reset_date = from_union([from_datetime, from_none], obj.get("resetDate"))
- return AccountQuotaSnapshot(entitlement_requests, overage, overage_allowed_with_exhausted_quota, remaining_percentage, used_requests, reset_date)
+ reasoning_effort = from_union([from_bool, from_none], obj.get("reasoningEffort"))
+ vision = from_union([from_bool, from_none], obj.get("vision"))
+ return ModelCapabilitiesOverrideSupports(reasoning_effort, vision)
def to_dict(self) -> dict:
result: dict = {}
- result["entitlementRequests"] = from_int(self.entitlement_requests)
- result["overage"] = from_int(self.overage)
- result["overageAllowedWithExhaustedQuota"] = from_bool(self.overage_allowed_with_exhausted_quota)
- result["remainingPercentage"] = to_float(self.remaining_percentage)
- result["usedRequests"] = from_int(self.used_requests)
- if self.reset_date is not None:
- result["resetDate"] = from_union([lambda x: x.isoformat(), from_none], self.reset_date)
+ if self.reasoning_effort is not None:
+ result["reasoningEffort"] = from_union([from_bool, from_none], self.reasoning_effort)
+ if self.vision is not None:
+ result["vision"] = from_union([from_bool, from_none], self.vision)
return result
@dataclass
-class AccountGetQuotaResult:
- quota_snapshots: dict[str, AccountQuotaSnapshot]
- """Quota snapshots keyed by type (e.g., chat, completions, premium_interactions)"""
+class AgentInfo:
+ description: str
+ """Description of the agent's purpose"""
+
+ display_name: str
+ """Human-readable display name"""
+
+ name: str
+ """Unique identifier of the custom agent"""
@staticmethod
- def from_dict(obj: Any) -> 'AccountGetQuotaResult':
+ def from_dict(obj: Any) -> 'AgentInfo':
assert isinstance(obj, dict)
- quota_snapshots = from_dict(AccountQuotaSnapshot.from_dict, obj.get("quotaSnapshots"))
- return AccountGetQuotaResult(quota_snapshots)
+ description = from_str(obj.get("description"))
+ display_name = from_str(obj.get("displayName"))
+ name = from_str(obj.get("name"))
+ return AgentInfo(description, display_name, name)
def to_dict(self) -> dict:
result: dict = {}
- result["quotaSnapshots"] = from_dict(lambda x: to_class(AccountQuotaSnapshot, x), self.quota_snapshots)
+ result["description"] = from_str(self.description)
+ result["displayName"] = from_str(self.display_name)
+ result["name"] = from_str(self.name)
return result
-class MCPConfigFilterMappingString(Enum):
- HIDDEN_CHARACTERS = "hidden_characters"
- MARKDOWN = "markdown"
- NONE = "none"
-
-class MCPConfigType(Enum):
- """Remote transport type. Defaults to "http" when omitted."""
+class MCPServerStatus(Enum):
+ """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured"""
- HTTP = "http"
- LOCAL = "local"
- SSE = "sse"
- STDIO = "stdio"
+ CONNECTED = "connected"
+ DISABLED = "disabled"
+ FAILED = "failed"
+ NEEDS_AUTH = "needs-auth"
+ NOT_CONFIGURED = "not_configured"
+ PENDING = "pending"
@dataclass
-class MCPConfigServer:
- """MCP server configuration (local/stdio or remote/http)"""
-
- args: list[str] | None = None
- command: str | None = None
- cwd: str | None = None
- env: dict[str, str] | None = None
- filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None
- is_default_server: bool | None = None
- timeout: int | None = None
- """Timeout in milliseconds for tool calls to this server."""
+class ToolCallResult:
+ text_result_for_llm: str
+ """Text result to send back to the LLM"""
- tools: list[str] | None = None
- """Tools to include. Defaults to all tools if not specified."""
+ error: str | None = None
+ """Error message if the tool call failed"""
- type: MCPConfigType | None = None
- """Remote transport type. Defaults to "http" when omitted."""
+ result_type: str | None = None
+ """Type of the tool result"""
- headers: dict[str, str] | None = None
- oauth_client_id: str | None = None
- oauth_public_client: bool | None = None
- url: str | None = None
+ tool_telemetry: dict[str, Any] | None = None
+ """Telemetry data from tool execution"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigServer':
+ def from_dict(obj: Any) -> 'ToolCallResult':
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(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, 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"))
- type = from_union([MCPConfigType, from_none], obj.get("type"))
- headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
- oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
- oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
- url = from_union([from_str, from_none], obj.get("url"))
- return MCPConfigServer(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+ text_result_for_llm = from_str(obj.get("textResultForLlm"))
+ error = from_union([from_str, from_none], obj.get("error"))
+ result_type = from_union([from_str, from_none], obj.get("resultType"))
+ tool_telemetry = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("toolTelemetry"))
+ return ToolCallResult(text_result_for_llm, error, result_type, tool_telemetry)
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(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping)
- if self.is_default_server is not None:
- result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server)
- if self.timeout is not None:
- result["timeout"] = from_union([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(MCPConfigType, x), from_none], self.type)
- if self.headers is not None:
- result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
- if self.oauth_client_id is not None:
- result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
- if self.oauth_public_client is not None:
- result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
- if self.url is not None:
- result["url"] = from_union([from_str, from_none], self.url)
+ result["textResultForLlm"] = from_str(self.text_result_for_llm)
+ if self.error is not None:
+ result["error"] = from_union([from_str, from_none], self.error)
+ if self.result_type is not None:
+ result["resultType"] = from_union([from_str, from_none], self.result_type)
+ if self.tool_telemetry is not None:
+ result["toolTelemetry"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.tool_telemetry)
return result
@dataclass
-class MCPConfigList:
- servers: dict[str, MCPConfigServer]
- """All MCP servers from user config, keyed by name"""
+class HandleToolCallResult:
+ success: bool
+ """Whether the tool call result was handled successfully"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigList':
+ def from_dict(obj: Any) -> 'HandleToolCallResult':
assert isinstance(obj, dict)
- servers = from_dict(MCPConfigServer.from_dict, obj.get("servers"))
- return MCPConfigList(servers)
+ success = from_bool(obj.get("success"))
+ return HandleToolCallResult(success)
def to_dict(self) -> dict:
result: dict = {}
- result["servers"] = from_dict(lambda x: to_class(MCPConfigServer, x), self.servers)
+ result["success"] = from_bool(self.success)
return result
+class UIElicitationStringEnumFieldType(Enum):
+ STRING = "string"
+
@dataclass
-class MCPConfigAddConfig:
- """MCP server configuration (local/stdio or remote/http)"""
+class UIElicitationStringOneOfFieldOneOf:
+ const: str
+ title: str
- args: list[str] | None = None
- command: str | None = None
- cwd: str | None = None
- env: dict[str, str] | None = None
- filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None
- is_default_server: bool | None = None
- timeout: int | None = None
- """Timeout in milliseconds for tool calls to this server."""
+ @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)
- tools: list[str] | None = None
- """Tools to include. Defaults to all tools if not specified."""
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["const"] = from_str(self.const)
+ result["title"] = from_str(self.title)
+ return result
- type: MCPConfigType | None = None
- """Remote transport type. Defaults to "http" when omitted."""
+class UIElicitationArrayEnumFieldType(Enum):
+ ARRAY = "array"
- headers: dict[str, str] | None = None
- oauth_client_id: str | None = None
- oauth_public_client: bool | None = None
- url: str | None = None
+@dataclass
+class PurpleUIElicitationArrayAnyOfFieldItemsAnyOf:
+ const: str
+ title: str
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigAddConfig':
+ def from_dict(obj: Any) -> 'PurpleUIElicitationArrayAnyOfFieldItemsAnyOf':
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(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, 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"))
- type = from_union([MCPConfigType, from_none], obj.get("type"))
- headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
- oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
- oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
- url = from_union([from_str, from_none], obj.get("url"))
- return MCPConfigAddConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+ const = from_str(obj.get("const"))
+ title = from_str(obj.get("title"))
+ return PurpleUIElicitationArrayAnyOfFieldItemsAnyOf(const, title)
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(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping)
- if self.is_default_server is not None:
- result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server)
- if self.timeout is not None:
- result["timeout"] = from_union([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(MCPConfigType, x), from_none], self.type)
- if self.headers is not None:
- result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
- if self.oauth_client_id is not None:
- result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
- if self.oauth_public_client is not None:
- result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
- if self.url is not None:
- result["url"] = from_union([from_str, from_none], self.url)
+ result["const"] = from_str(self.const)
+ result["title"] = from_str(self.title)
return result
-@dataclass
-class MCPConfigAddRequest:
- config: MCPConfigAddConfig
- """MCP server configuration (local/stdio or remote/http)"""
+class UIElicitationResponseAction(Enum):
+ """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)"""
- name: str
- """Unique name for the MCP server"""
+ ACCEPT = "accept"
+ CANCEL = "cancel"
+ DECLINE = "decline"
+
+@dataclass
+class UIElicitationResult:
+ success: bool
+ """Whether the response was accepted. False if the request was already resolved by another
+ client.
+ """
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigAddRequest':
+ def from_dict(obj: Any) -> 'UIElicitationResult':
assert isinstance(obj, dict)
- config = MCPConfigAddConfig.from_dict(obj.get("config"))
- name = from_str(obj.get("name"))
- return MCPConfigAddRequest(config, name)
+ success = from_bool(obj.get("success"))
+ return UIElicitationResult(success)
def to_dict(self) -> dict:
result: dict = {}
- result["config"] = to_class(MCPConfigAddConfig, self.config)
- result["name"] = from_str(self.name)
+ result["success"] = from_bool(self.success)
return result
+class Kind(Enum):
+ APPROVED = "approved"
+ DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy"
+ DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook"
+ DENIED_BY_RULES = "denied-by-rules"
+ DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user"
+ DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user"
+
@dataclass
-class MCPConfigUpdateConfig:
- """MCP server configuration (local/stdio or remote/http)"""
+class PermissionRequestResult:
+ success: bool
+ """Whether the permission request was handled successfully"""
- args: list[str] | None = None
- command: str | None = None
- cwd: str | None = None
- env: dict[str, str] | None = None
- filter_mapping: dict[str, MCPConfigFilterMappingString] | MCPConfigFilterMappingString | None = None
- is_default_server: bool | None = None
- timeout: int | None = None
- """Timeout in milliseconds for tool calls to this server."""
+ @staticmethod
+ def from_dict(obj: Any) -> 'PermissionRequestResult':
+ assert isinstance(obj, dict)
+ success = from_bool(obj.get("success"))
+ return PermissionRequestResult(success)
- tools: list[str] | None = None
- """Tools to include. Defaults to all tools if not specified."""
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["success"] = from_bool(self.success)
+ return result
- type: MCPConfigType | None = None
- """Remote transport type. Defaults to "http" when omitted."""
+@dataclass
+class PingResult:
+ message: str
+ """Echoed message (or default greeting)"""
- headers: dict[str, str] | None = None
- oauth_client_id: str | None = None
- oauth_public_client: bool | None = None
- url: str | None = None
+ protocol_version: int
+ """Server protocol version number"""
+
+ timestamp: int
+ """Server timestamp in milliseconds"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigUpdateConfig':
+ def from_dict(obj: Any) -> 'PingResult':
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(MCPConfigFilterMappingString, x), MCPConfigFilterMappingString, 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"))
- type = from_union([MCPConfigType, from_none], obj.get("type"))
- headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
- oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
- oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
- url = from_union([from_str, from_none], obj.get("url"))
- return MCPConfigUpdateConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+ 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)
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(MCPConfigFilterMappingString, x), x), lambda x: to_enum(MCPConfigFilterMappingString, x), from_none], self.filter_mapping)
- if self.is_default_server is not None:
- result["isDefaultServer"] = from_union([from_bool, from_none], self.is_default_server)
- if self.timeout is not None:
- result["timeout"] = from_union([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(MCPConfigType, x), from_none], self.type)
- if self.headers is not None:
- result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
- if self.oauth_client_id is not None:
- result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
- if self.oauth_public_client is not None:
- result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
- if self.url is not None:
- result["url"] = from_union([from_str, from_none], self.url)
+ result["message"] = from_str(self.message)
+ result["protocolVersion"] = from_int(self.protocol_version)
+ result["timestamp"] = from_int(self.timestamp)
return result
@dataclass
-class MCPConfigUpdateRequest:
- config: MCPConfigUpdateConfig
- """MCP server configuration (local/stdio or remote/http)"""
-
- name: str
- """Name of the MCP server to update"""
+class PingRequest:
+ message: str | None = None
+ """Optional message to echo back"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigUpdateRequest':
+ def from_dict(obj: Any) -> 'PingRequest':
assert isinstance(obj, dict)
- config = MCPConfigUpdateConfig.from_dict(obj.get("config"))
- name = from_str(obj.get("name"))
- return MCPConfigUpdateRequest(config, name)
+ message = from_union([from_str, from_none], obj.get("message"))
+ return PingRequest(message)
def to_dict(self) -> dict:
result: dict = {}
- result["config"] = to_class(MCPConfigUpdateConfig, self.config)
- result["name"] = from_str(self.name)
+ if self.message is not None:
+ result["message"] = from_union([from_str, from_none], self.message)
return result
@dataclass
-class MCPConfigRemoveRequest:
- name: str
- """Name of the MCP server to remove"""
+class ModelBilling:
+ """Billing information"""
+
+ multiplier: float
+ """Billing cost multiplier relative to the base rate"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPConfigRemoveRequest':
+ def from_dict(obj: Any) -> 'ModelBilling':
assert isinstance(obj, dict)
- name = from_str(obj.get("name"))
- return MCPConfigRemoveRequest(name)
+ multiplier = from_float(obj.get("multiplier"))
+ return ModelBilling(multiplier)
def to_dict(self) -> dict:
result: dict = {}
- result["name"] = from_str(self.name)
+ result["multiplier"] = to_float(self.multiplier)
return result
-class MCPServerSource(Enum):
- """Configuration source
+@dataclass
+class FluffyModelCapabilitiesLimitsVision:
+ """Vision-specific limits"""
- Configuration source: user, workspace, plugin, or builtin
- """
- BUILTIN = "builtin"
- PLUGIN = "plugin"
- USER = "user"
- WORKSPACE = "workspace"
+ max_prompt_image_size: int
+ """Maximum image size in bytes"""
-class DiscoveredMCPServerType(Enum):
- """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)"""
+ max_prompt_images: int
+ """Maximum number of images per prompt"""
- HTTP = "http"
- MEMORY = "memory"
- SSE = "sse"
- STDIO = "stdio"
+ supported_media_types: list[str]
+ """MIME types the model accepts"""
-@dataclass
-class DiscoveredMCPServer:
- enabled: bool
- """Whether the server is enabled (not in the disabled list)"""
+ @staticmethod
+ def from_dict(obj: Any) -> 'FluffyModelCapabilitiesLimitsVision':
+ assert isinstance(obj, dict)
+ max_prompt_image_size = from_int(obj.get("max_prompt_image_size"))
+ max_prompt_images = from_int(obj.get("max_prompt_images"))
+ supported_media_types = from_list(from_str, obj.get("supported_media_types"))
+ return FluffyModelCapabilitiesLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
- name: str
- """Server name (config key)"""
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["max_prompt_image_size"] = from_int(self.max_prompt_image_size)
+ result["max_prompt_images"] = from_int(self.max_prompt_images)
+ result["supported_media_types"] = from_list(from_str, self.supported_media_types)
+ return result
- source: MCPServerSource
- """Configuration source"""
+@dataclass
+class CapabilitiesSupports:
+ """Feature flags indicating what the model supports"""
- type: DiscoveredMCPServerType | None = None
- """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)"""
+ reasoning_effort: bool | None = None
+ """Whether this model supports reasoning effort configuration"""
+
+ vision: bool | None = None
+ """Whether this model supports vision/image input"""
@staticmethod
- def from_dict(obj: Any) -> 'DiscoveredMCPServer':
+ def from_dict(obj: Any) -> 'CapabilitiesSupports':
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)
+ reasoning_effort = from_union([from_bool, from_none], obj.get("reasoningEffort"))
+ vision = from_union([from_bool, from_none], obj.get("vision"))
+ return CapabilitiesSupports(reasoning_effort, vision)
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.reasoning_effort is not None:
+ result["reasoningEffort"] = from_union([from_bool, from_none], self.reasoning_effort)
+ if self.vision is not None:
+ result["vision"] = from_union([from_bool, from_none], self.vision)
return result
@dataclass
-class MCPDiscoverResult:
- servers: list[DiscoveredMCPServer]
- """MCP servers discovered from all sources"""
+class ModelPolicy:
+ """Policy state (if applicable)"""
+
+ state: str
+ """Current policy state for this model"""
+
+ terms: str
+ """Usage terms or conditions for this model"""
@staticmethod
- def from_dict(obj: Any) -> 'MCPDiscoverResult':
+ def from_dict(obj: Any) -> 'ModelPolicy':
assert isinstance(obj, dict)
- servers = from_list(DiscoveredMCPServer.from_dict, obj.get("servers"))
- return MCPDiscoverResult(servers)
+ state = from_str(obj.get("state"))
+ terms = from_str(obj.get("terms"))
+ return ModelPolicy(state, terms)
def to_dict(self) -> dict:
result: dict = {}
- result["servers"] = from_list(lambda x: to_class(DiscoveredMCPServer, x), self.servers)
+ result["state"] = from_str(self.state)
+ result["terms"] = from_str(self.terms)
return result
@dataclass
-class MCPDiscoverRequest:
- working_directory: str | None = None
- """Working directory used as context for discovery (e.g., plugin resolution)"""
+class Tool:
+ 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) -> 'MCPDiscoverRequest':
+ def from_dict(obj: Any) -> 'Tool':
assert isinstance(obj, dict)
- working_directory = from_union([from_str, from_none], obj.get("workingDirectory"))
- return MCPDiscoverRequest(working_directory)
+ 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 = {}
- if self.working_directory is not None:
- result["workingDirectory"] = from_union([from_str, from_none], self.working_directory)
+ 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 SkillsConfigSetDisabledSkillsRequest:
- disabled_skills: list[str]
- """List of skill names to disable"""
+class ToolsListRequest:
+ model: str | None = None
+ """Optional model ID — when provided, the returned tool list reflects model-specific
+ overrides
+ """
@staticmethod
- def from_dict(obj: Any) -> 'SkillsConfigSetDisabledSkillsRequest':
+ def from_dict(obj: Any) -> 'ToolsListRequest':
assert isinstance(obj, dict)
- disabled_skills = from_list(from_str, obj.get("disabledSkills"))
- return SkillsConfigSetDisabledSkillsRequest(disabled_skills)
+ model = from_union([from_str, from_none], obj.get("model"))
+ return ToolsListRequest(model)
def to_dict(self) -> dict:
result: dict = {}
- result["disabledSkills"] = from_list(from_str, self.disabled_skills)
+ if self.model is not None:
+ result["model"] = from_union([from_str, from_none], self.model)
return result
@dataclass
-class ServerSkill:
- description: str
- """Description of what the skill does"""
+class AccountQuotaSnapshot:
+ entitlement_requests: int
+ """Number of requests included in the entitlement"""
- enabled: bool
- """Whether the skill is currently enabled (based on global config)"""
+ overage: int
+ """Number of overage requests made this period"""
- name: str
- """Unique identifier for the skill"""
+ overage_allowed_with_exhausted_quota: bool
+ """Whether pay-per-request usage is allowed when quota is exhausted"""
- source: str
- """Source location type (e.g., project, personal-copilot, plugin, builtin)"""
+ remaining_percentage: float
+ """Percentage of entitlement remaining"""
- user_invocable: bool
- """Whether the skill can be invoked by the user as a slash command"""
+ used_requests: int
+ """Number of requests used so far this period"""
- path: str | None = None
- """Absolute path to the skill file"""
+ reset_date: datetime | None = None
+ """Date when the quota resets (ISO 8601)"""
- project_path: str | None = None
- """The project path this skill belongs to (only for project/inherited skills)"""
+ @staticmethod
+ def from_dict(obj: Any) -> 'AccountQuotaSnapshot':
+ assert isinstance(obj, dict)
+ entitlement_requests = from_int(obj.get("entitlementRequests"))
+ overage = from_int(obj.get("overage"))
+ overage_allowed_with_exhausted_quota = from_bool(obj.get("overageAllowedWithExhaustedQuota"))
+ remaining_percentage = from_float(obj.get("remainingPercentage"))
+ used_requests = from_int(obj.get("usedRequests"))
+ reset_date = from_union([from_datetime, from_none], obj.get("resetDate"))
+ return AccountQuotaSnapshot(entitlement_requests, overage, overage_allowed_with_exhausted_quota, remaining_percentage, used_requests, reset_date)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["entitlementRequests"] = from_int(self.entitlement_requests)
+ result["overage"] = from_int(self.overage)
+ result["overageAllowedWithExhaustedQuota"] = from_bool(self.overage_allowed_with_exhausted_quota)
+ result["remainingPercentage"] = to_float(self.remaining_percentage)
+ result["usedRequests"] = from_int(self.used_requests)
+ if self.reset_date is not None:
+ result["resetDate"] = from_union([lambda x: x.isoformat(), from_none], self.reset_date)
+ return result
+
+@dataclass
+class MCPConfigRemoveRequest:
+ name: str
+ """Name of the MCP server to remove"""
@staticmethod
- def from_dict(obj: Any) -> 'ServerSkill':
+ def from_dict(obj: Any) -> 'MCPConfigRemoveRequest':
assert isinstance(obj, dict)
- description = from_str(obj.get("description"))
- enabled = from_bool(obj.get("enabled"))
name = from_str(obj.get("name"))
- source = from_str(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 MCPConfigRemoveRequest(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"] = from_str(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 ServerSkillList:
- skills: list[ServerSkill]
- """All discovered skills across all sources"""
+class MCPDiscoverRequest:
+ working_directory: str | None = None
+ """Working directory used as context for discovery (e.g., plugin resolution)"""
@staticmethod
- def from_dict(obj: Any) -> 'ServerSkillList':
+ def from_dict(obj: Any) -> 'MCPDiscoverRequest':
assert isinstance(obj, dict)
- skills = from_list(ServerSkill.from_dict, obj.get("skills"))
- return ServerSkillList(skills)
+ working_directory = from_union([from_str, from_none], obj.get("workingDirectory"))
+ return MCPDiscoverRequest(working_directory)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ if self.working_directory is not None:
+ result["workingDirectory"] = from_union([from_str, from_none], self.working_directory)
+ return result
+
+@dataclass
+class SkillsConfigSetDisabledSkillsRequest:
+ disabled_skills: list[str]
+ """List of skill names to disable"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SkillsConfigSetDisabledSkillsRequest':
+ assert isinstance(obj, dict)
+ disabled_skills = from_list(from_str, obj.get("disabledSkills"))
+ return SkillsConfigSetDisabledSkillsRequest(disabled_skills)
def to_dict(self) -> dict:
result: dict = {}
- result["skills"] = from_list(lambda x: to_class(ServerSkill, x), self.skills)
+ result["disabledSkills"] = from_list(from_str, self.disabled_skills)
return result
@dataclass
@@ -981,32 +857,6 @@ class SessionFSSetProviderConventions(Enum):
POSIX = "posix"
WINDOWS = "windows"
-@dataclass
-class SessionFSSetProviderRequest:
- conventions: SessionFSSetProviderConventions
- """Path conventions used by this filesystem"""
-
- initial_cwd: str
- """Initial working directory for sessions"""
-
- session_state_path: str
- """Path within each session's SessionFs where the runtime stores files for that session"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSSetProviderRequest':
- assert isinstance(obj, dict)
- conventions = SessionFSSetProviderConventions(obj.get("conventions"))
- initial_cwd = from_str(obj.get("initialCwd"))
- session_state_path = from_str(obj.get("sessionStatePath"))
- return SessionFSSetProviderRequest(conventions, initial_cwd, session_state_path)
-
- 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)
- return result
-
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class SessionsForkResult:
@@ -1050,24 +900,7 @@ def to_dict(self) -> dict:
return result
@dataclass
-class CurrentModel:
- model_id: str | None = None
- """Currently active model identifier"""
-
- @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)
-
- 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)
- return result
-
-@dataclass
-class ModelSwitchToResult:
+class ModelSwitchToResult:
model_id: str | None = None
"""Currently active model identifier after the switch"""
@@ -1084,7 +917,7 @@ def to_dict(self) -> dict:
return result
@dataclass
-class ModelCapabilitiesOverrideLimitsVision:
+class FluffyModelCapabilitiesOverrideLimitsVision:
max_prompt_image_size: int | None = None
"""Maximum image size in bytes"""
@@ -1095,12 +928,12 @@ class ModelCapabilitiesOverrideLimitsVision:
"""MIME types the model accepts"""
@staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimitsVision':
+ def from_dict(obj: Any) -> 'FluffyModelCapabilitiesOverrideLimitsVision':
assert isinstance(obj, dict)
max_prompt_image_size = from_union([from_int, from_none], obj.get("max_prompt_image_size"))
max_prompt_images = from_union([from_int, from_none], obj.get("max_prompt_images"))
supported_media_types = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supported_media_types"))
- return ModelCapabilitiesOverrideLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
+ return FluffyModelCapabilitiesOverrideLimitsVision(max_prompt_image_size, max_prompt_images, supported_media_types)
def to_dict(self) -> dict:
result: dict = {}
@@ -1112,113 +945,6 @@ def to_dict(self) -> dict:
result["supported_media_types"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_media_types)
return result
-@dataclass
-class ModelCapabilitiesOverrideLimits:
- """Token limits for prompts, outputs, and context window"""
-
- max_context_window_tokens: int | None = None
- """Maximum total context window size in tokens"""
-
- max_output_tokens: int | None = None
- max_prompt_tokens: int | None = None
- vision: ModelCapabilitiesOverrideLimitsVision | None = None
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideLimits':
- assert isinstance(obj, dict)
- max_context_window_tokens = from_union([from_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 ModelCapabilitiesOverrideSupports:
- """Feature flags indicating what the model supports"""
-
- reasoning_effort: bool | None = None
- vision: bool | None = None
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilitiesOverrideSupports':
- assert isinstance(obj, dict)
- reasoning_effort = from_union([from_bool, from_none], obj.get("reasoningEffort"))
- vision = from_union([from_bool, from_none], obj.get("vision"))
- return ModelCapabilitiesOverrideSupports(reasoning_effort, vision)
-
- def to_dict(self) -> dict:
- result: dict = {}
- if self.reasoning_effort is not None:
- result["reasoningEffort"] = from_union([from_bool, from_none], self.reasoning_effort)
- if self.vision is not None:
- result["vision"] = from_union([from_bool, from_none], self.vision)
- return result
-
-@dataclass
-class ModelCapabilitiesOverride:
- """Override individual model capabilities resolved by the runtime"""
-
- limits: ModelCapabilitiesOverrideLimits | None = None
- """Token limits for prompts, outputs, and context window"""
-
- supports: ModelCapabilitiesOverrideSupports | None = None
- """Feature flags indicating what the model supports"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModelCapabilitiesOverride':
- 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)
-
- 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
-
-@dataclass
-class ModelSwitchToRequest:
- model_id: str
- """Model identifier to switch to"""
-
- model_capabilities: ModelCapabilitiesOverride | None = None
- """Override individual model capabilities resolved by the runtime"""
-
- reasoning_effort: str | None = None
- """Reasoning effort level to use for the model"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModelSwitchToRequest':
- assert isinstance(obj, dict)
- model_id = from_str(obj.get("modelId"))
- model_capabilities = from_union([ModelCapabilitiesOverride.from_dict, from_none], obj.get("modelCapabilities"))
- reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort"))
- return ModelSwitchToRequest(model_id, model_capabilities, reasoning_effort)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["modelId"] = from_str(self.model_id)
- if self.model_capabilities is not None:
- result["modelCapabilities"] = from_union([lambda x: to_class(ModelCapabilitiesOverride, x), from_none], self.model_capabilities)
- if self.reasoning_effort is not None:
- result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort)
- return result
-
class SessionMode(Enum):
"""The agent mode. Valid values: "interactive", "plan", "autopilot"."""
@@ -1226,22 +952,6 @@ class SessionMode(Enum):
INTERACTIVE = "interactive"
PLAN = "plan"
-@dataclass
-class ModeSetRequest:
- mode: SessionMode
- """The agent mode. Valid values: "interactive", "plan", "autopilot"."""
-
- @staticmethod
- def from_dict(obj: Any) -> 'ModeSetRequest':
- assert isinstance(obj, dict)
- mode = SessionMode(obj.get("mode"))
- return ModeSetRequest(mode)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["mode"] = to_enum(SessionMode, self.mode)
- return result
-
@dataclass
class NameGetResult:
name: str | None = None
@@ -1325,101 +1035,6 @@ class SessionSyncLevel(Enum):
REPO_AND_USER = "repo_and_user"
USER = "user"
-@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
- pr_create_sync_dismissed: bool | None = None
- repository: str | None = None
- session_sync_level: SessionSyncLevel | None = None
- summary: str | None = None
- summary_count: int | None = None
- updated_at: datetime | 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([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"))
- pr_create_sync_dismissed = from_union([from_bool, from_none], obj.get("pr_create_sync_dismissed"))
- repository = from_union([from_str, from_none], obj.get("repository"))
- session_sync_level = from_union([SessionSyncLevel, from_none], obj.get("session_sync_level"))
- summary = from_union([from_str, from_none], obj.get("summary"))
- summary_count = from_union([from_int, from_none], obj.get("summary_count"))
- updated_at = from_union([from_datetime, from_none], obj.get("updated_at"))
- 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, pr_create_sync_dismissed, repository, session_sync_level, summary, summary_count, updated_at)
-
- 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.pr_create_sync_dismissed is not None:
- result["pr_create_sync_dismissed"] = from_union([from_bool, from_none], self.pr_create_sync_dismissed)
- if self.repository is not None:
- result["repository"] = from_union([from_str, from_none], self.repository)
- if self.session_sync_level is not None:
- result["session_sync_level"] = from_union([lambda x: to_enum(SessionSyncLevel, x), from_none], self.session_sync_level)
- if self.summary is not None:
- result["summary"] = from_union([from_str, from_none], self.summary)
- 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)
- return result
-
-@dataclass
-class WorkspacesGetWorkspaceResult:
- workspace: Workspace | None = None
- """Current workspace metadata, or null if not available"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'WorkspacesGetWorkspaceResult':
- assert isinstance(obj, dict)
- workspace = from_union([Workspace.from_dict, from_none], obj.get("workspace"))
- return WorkspacesGetWorkspaceResult(workspace)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["workspace"] = from_union([lambda x: to_class(Workspace, x), from_none], self.workspace)
- return result
-
@dataclass
class WorkspacesListFilesResult:
files: list[str]
@@ -1489,6 +1104,23 @@ def to_dict(self) -> dict:
result["path"] = from_str(self.path)
return result
+class InstructionsSourcesLocation(Enum):
+ """Where this source lives — used for UI grouping"""
+
+ REPOSITORY = "repository"
+ USER = "user"
+ WORKING_DIRECTORY = "working-directory"
+
+class InstructionsSourcesType(Enum):
+ """Category of instruction source — used for merge logic"""
+
+ CHILD_INSTRUCTIONS = "child-instructions"
+ HOME = "home"
+ MODEL = "model"
+ NESTED_AGENTS = "nested-agents"
+ REPO = "repo"
+ VSCODE = "vscode"
+
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class FleetStartResult:
@@ -1525,7 +1157,7 @@ def to_dict(self) -> dict:
return result
@dataclass
-class Agent:
+class AgentListAgent:
description: str
"""Description of the agent's purpose"""
@@ -1536,12 +1168,12 @@ class Agent:
"""Unique identifier of the custom agent"""
@staticmethod
- def from_dict(obj: Any) -> 'Agent':
+ def from_dict(obj: Any) -> 'AgentListAgent':
assert isinstance(obj, dict)
description = from_str(obj.get("description"))
display_name = from_str(obj.get("displayName"))
name = from_str(obj.get("name"))
- return Agent(description, display_name, name)
+ return AgentListAgent(description, display_name, name)
def to_dict(self) -> dict:
result: dict = {}
@@ -1550,25 +1182,10 @@ def to_dict(self) -> dict:
result["name"] = from_str(self.name)
return result
-# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class AgentList:
- agents: list[Agent]
- """Available custom agents"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'AgentList':
- assert isinstance(obj, dict)
- agents = from_list(Agent.from_dict, obj.get("agents"))
- return AgentList(agents)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["agents"] = from_list(lambda x: to_class(Agent, x), self.agents)
- return result
+class AgentSelectResultAgent:
+ """The newly selected custom agent"""
-@dataclass
-class AgentGetCurrentResultAgent:
description: str
"""Description of the agent's purpose"""
@@ -1579,12 +1196,12 @@ class AgentGetCurrentResultAgent:
"""Unique identifier of the custom agent"""
@staticmethod
- def from_dict(obj: Any) -> 'AgentGetCurrentResultAgent':
+ def from_dict(obj: Any) -> 'AgentSelectResultAgent':
assert isinstance(obj, dict)
description = from_str(obj.get("description"))
display_name = from_str(obj.get("displayName"))
name = from_str(obj.get("name"))
- return AgentGetCurrentResultAgent(description, display_name, name)
+ return AgentSelectResultAgent(description, display_name, name)
def to_dict(self) -> dict:
result: dict = {}
@@ -1595,74 +1212,12 @@ def to_dict(self) -> dict:
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class AgentGetCurrentResult:
- agent: AgentGetCurrentResultAgent | None = None
- """Currently selected custom agent, or null if using the default agent"""
+class AgentSelectRequest:
+ name: str
+ """Name of the custom agent to select"""
@staticmethod
- def from_dict(obj: Any) -> 'AgentGetCurrentResult':
- assert isinstance(obj, dict)
- agent = from_union([AgentGetCurrentResultAgent.from_dict, from_none], obj.get("agent"))
- return AgentGetCurrentResult(agent)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["agent"] = from_union([lambda x: to_class(AgentGetCurrentResultAgent, x), from_none], self.agent)
- return result
-
-@dataclass
-class AgentSelectAgent:
- """The newly selected custom agent"""
-
- description: str
- """Description of the agent's purpose"""
-
- display_name: str
- """Human-readable display name"""
-
- name: str
- """Unique identifier of the custom agent"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'AgentSelectAgent':
- assert isinstance(obj, dict)
- description = from_str(obj.get("description"))
- display_name = from_str(obj.get("displayName"))
- name = from_str(obj.get("name"))
- return AgentSelectAgent(description, display_name, 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)
- return result
-
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class AgentSelectResult:
- agent: AgentSelectAgent
- """The newly selected custom agent"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'AgentSelectResult':
- assert isinstance(obj, dict)
- agent = AgentSelectAgent.from_dict(obj.get("agent"))
- return AgentSelectResult(agent)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["agent"] = to_class(AgentSelectAgent, self.agent)
- return result
-
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class AgentSelectRequest:
- name: str
- """Name of the custom agent to select"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'AgentSelectRequest':
+ def from_dict(obj: Any) -> 'AgentSelectRequest':
assert isinstance(obj, dict)
name = from_str(obj.get("name"))
return AgentSelectRequest(name)
@@ -1673,7 +1228,7 @@ def to_dict(self) -> dict:
return result
@dataclass
-class AgentReloadAgent:
+class AgentReloadResultAgent:
description: str
"""Description of the agent's purpose"""
@@ -1684,12 +1239,12 @@ class AgentReloadAgent:
"""Unique identifier of the custom agent"""
@staticmethod
- def from_dict(obj: Any) -> 'AgentReloadAgent':
+ def from_dict(obj: Any) -> 'AgentReloadResultAgent':
assert isinstance(obj, dict)
description = from_str(obj.get("description"))
display_name = from_str(obj.get("displayName"))
name = from_str(obj.get("name"))
- return AgentReloadAgent(description, display_name, name)
+ return AgentReloadResultAgent(description, display_name, name)
def to_dict(self) -> dict:
result: dict = {}
@@ -1698,23 +1253,6 @@ def to_dict(self) -> dict:
result["name"] = from_str(self.name)
return result
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class AgentReloadResult:
- agents: list[AgentReloadAgent]
- """Reloaded custom agents"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'AgentReloadResult':
- assert isinstance(obj, dict)
- agents = from_list(AgentReloadAgent.from_dict, obj.get("agents"))
- return AgentReloadResult(agents)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["agents"] = from_list(lambda x: to_class(AgentReloadAgent, x), self.agents)
- return result
-
@dataclass
class Skill:
description: str
@@ -1757,23 +1295,6 @@ def to_dict(self) -> dict:
result["path"] = from_union([from_str, from_none], self.path)
return result
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class SkillList:
- skills: list[Skill]
- """Available skills"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'SkillList':
- assert isinstance(obj, dict)
- skills = from_list(Skill.from_dict, obj.get("skills"))
- return SkillList(skills)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills)
- return result
-
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class SkillsEnableRequest:
@@ -1808,65 +1329,6 @@ def to_dict(self) -> dict:
result["name"] = from_str(self.name)
return result
-class MCPServerStatus(Enum):
- """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured"""
-
- CONNECTED = "connected"
- DISABLED = "disabled"
- FAILED = "failed"
- NEEDS_AUTH = "needs-auth"
- NOT_CONFIGURED = "not_configured"
- PENDING = "pending"
-
-@dataclass
-class MCPServer:
- name: str
- """Server name (config key)"""
-
- status: MCPServerStatus
- """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured"""
-
- error: str | None = None
- """Error message if the server failed to connect"""
-
- source: MCPServerSource | None = None
- """Configuration source: user, workspace, plugin, or builtin"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'MCPServer':
- assert isinstance(obj, dict)
- name = from_str(obj.get("name"))
- status = MCPServerStatus(obj.get("status"))
- error = from_union([from_str, from_none], obj.get("error"))
- source = from_union([MCPServerSource, from_none], obj.get("source"))
- return MCPServer(name, status, error, source)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["name"] = from_str(self.name)
- result["status"] = to_enum(MCPServerStatus, self.status)
- if self.error is not None:
- result["error"] = from_union([from_str, from_none], self.error)
- if self.source is not None:
- result["source"] = from_union([lambda x: to_enum(MCPServerSource, x), from_none], self.source)
- return result
-
-@dataclass
-class MCPServerList:
- 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
-
@dataclass
class MCPEnableRequest:
server_name: str
@@ -1931,23 +1393,6 @@ def to_dict(self) -> dict:
result["version"] = from_union([from_str, from_none], self.version)
return result
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class PluginList:
- plugins: list[Plugin]
- """Installed plugins"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'PluginList':
- assert isinstance(obj, dict)
- plugins = from_list(Plugin.from_dict, obj.get("plugins"))
- return PluginList(plugins)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["plugins"] = from_list(lambda x: to_class(Plugin, x), self.plugins)
- return result
-
class ExtensionSource(Enum):
"""Discovery source: project (.github/extensions/) or user (~/.copilot/extensions/)"""
@@ -1962,60 +1407,6 @@ class ExtensionStatus(Enum):
RUNNING = "running"
STARTING = "starting"
-@dataclass
-class Extension:
- 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
-
-# Experimental: this type is part of an experimental API and may change or be removed.
-@dataclass
-class ExtensionList:
- extensions: list[Extension]
- """Discovered extensions and their current status"""
-
- @staticmethod
- def from_dict(obj: Any) -> 'ExtensionList':
- assert isinstance(obj, dict)
- extensions = from_list(Extension.from_dict, obj.get("extensions"))
- return ExtensionList(extensions)
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions)
- return result
-
# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
class ExtensionsEnableRequest:
@@ -2051,15 +1442,15 @@ def to_dict(self) -> dict:
return result
@dataclass
-class HandleToolCallResult:
+class CommandsHandlePendingCommandResult:
success: bool
- """Whether the tool call result was handled successfully"""
+ """Whether the command was handled successfully"""
@staticmethod
- def from_dict(obj: Any) -> 'HandleToolCallResult':
+ def from_dict(obj: Any) -> 'CommandsHandlePendingCommandResult':
assert isinstance(obj, dict)
success = from_bool(obj.get("success"))
- return HandleToolCallResult(success)
+ return CommandsHandlePendingCommandResult(success)
def to_dict(self) -> dict:
result: dict = {}
@@ -2067,847 +1458,2314 @@ def to_dict(self) -> dict:
return result
@dataclass
-class ToolCallResult:
- text_result_for_llm: str
- """Text result to send back to the LLM"""
+class CommandsHandlePendingCommandRequest:
+ request_id: str
+ """Request ID from the command invocation event"""
error: str | None = None
- """Error message if the tool call failed"""
-
- result_type: str | None = None
- """Type of the tool result"""
-
- tool_telemetry: dict[str, Any] | None = None
- """Telemetry data from tool execution"""
+ """Error message if the command handler failed"""
@staticmethod
- def from_dict(obj: Any) -> 'ToolCallResult':
+ def from_dict(obj: Any) -> 'CommandsHandlePendingCommandRequest':
assert isinstance(obj, dict)
- text_result_for_llm = from_str(obj.get("textResultForLlm"))
+ request_id = from_str(obj.get("requestId"))
error = from_union([from_str, from_none], obj.get("error"))
- result_type = from_union([from_str, from_none], obj.get("resultType"))
- tool_telemetry = from_union([lambda x: from_dict(lambda x: x, x), from_none], obj.get("toolTelemetry"))
- return ToolCallResult(text_result_for_llm, error, result_type, tool_telemetry)
+ return CommandsHandlePendingCommandRequest(request_id, error)
def to_dict(self) -> dict:
result: dict = {}
- result["textResultForLlm"] = from_str(self.text_result_for_llm)
+ result["requestId"] = from_str(self.request_id)
if self.error is not None:
result["error"] = from_union([from_str, from_none], self.error)
- if self.result_type is not None:
- result["resultType"] = from_union([from_str, from_none], self.result_type)
- if self.tool_telemetry is not None:
- result["toolTelemetry"] = from_union([lambda x: from_dict(lambda x: x, x), from_none], self.tool_telemetry)
return result
+class UIElicitationSchemaPropertyStringFormat(Enum):
+ DATE = "date"
+ DATE_TIME = "date-time"
+ EMAIL = "email"
+ URI = "uri"
+
@dataclass
-class ToolsHandlePendingToolCallRequest:
- request_id: str
- """Request ID of the pending tool call"""
-
- error: str | None = None
- """Error message if the tool call failed"""
-
- result: ToolCallResult | str | None = None
- """Tool call result (string or expanded result object)"""
+class FluffyUIElicitationArrayAnyOfFieldItemsAnyOf:
+ const: str
+ title: str
@staticmethod
- def from_dict(obj: Any) -> 'ToolsHandlePendingToolCallRequest':
+ def from_dict(obj: Any) -> 'FluffyUIElicitationArrayAnyOfFieldItemsAnyOf':
assert isinstance(obj, dict)
- request_id = from_str(obj.get("requestId"))
- error = from_union([from_str, from_none], obj.get("error"))
- result = from_union([ToolCallResult.from_dict, from_str, from_none], obj.get("result"))
- return ToolsHandlePendingToolCallRequest(request_id, error, result)
+ const = from_str(obj.get("const"))
+ title = from_str(obj.get("title"))
+ return FluffyUIElicitationArrayAnyOfFieldItemsAnyOf(const, title)
def to_dict(self) -> dict:
result: dict = {}
- result["requestId"] = from_str(self.request_id)
- if self.error is not None:
- result["error"] = from_union([from_str, from_none], self.error)
- if self.result is not None:
- result["result"] = from_union([lambda x: to_class(ToolCallResult, x), from_str, from_none], self.result)
+ result["const"] = from_str(self.const)
+ result["title"] = from_str(self.title)
return result
@dataclass
-class CommandsHandlePendingCommandResult:
- success: bool
- """Whether the command was handled successfully"""
+class UIElicitationSchemaPropertyOneOf:
+ const: str
+ title: str
@staticmethod
- def from_dict(obj: Any) -> 'CommandsHandlePendingCommandResult':
+ def from_dict(obj: Any) -> 'UIElicitationSchemaPropertyOneOf':
assert isinstance(obj, dict)
- success = from_bool(obj.get("success"))
- return CommandsHandlePendingCommandResult(success)
+ const = from_str(obj.get("const"))
+ title = from_str(obj.get("title"))
+ return UIElicitationSchemaPropertyOneOf(const, title)
def to_dict(self) -> dict:
result: dict = {}
- result["success"] = from_bool(self.success)
+ result["const"] = from_str(self.const)
+ result["title"] = from_str(self.title)
return result
-@dataclass
-class CommandsHandlePendingCommandRequest:
- request_id: str
- """Request ID from the command invocation event"""
+class UIElicitationSchemaPropertyNumberType(Enum):
+ ARRAY = "array"
+ BOOLEAN = "boolean"
+ INTEGER = "integer"
+ NUMBER = "number"
+ STRING = "string"
- error: str | None = None
- """Error message if the command handler failed"""
+class RequestedSchemaType(Enum):
+ OBJECT = "object"
+
+@dataclass
+class LogResult:
+ event_id: UUID
+ """The unique identifier of the emitted session event"""
@staticmethod
- def from_dict(obj: Any) -> 'CommandsHandlePendingCommandRequest':
+ def from_dict(obj: Any) -> 'LogResult':
assert isinstance(obj, dict)
- request_id = from_str(obj.get("requestId"))
- error = from_union([from_str, from_none], obj.get("error"))
- return CommandsHandlePendingCommandRequest(request_id, error)
+ event_id = UUID(obj.get("eventId"))
+ return LogResult(event_id)
def to_dict(self) -> dict:
result: dict = {}
- result["requestId"] = from_str(self.request_id)
- if self.error is not None:
- result["error"] = from_union([from_str, from_none], self.error)
+ result["eventId"] = str(self.event_id)
return result
-class UIElicitationResponseAction(Enum):
- """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)"""
+class SessionLogLevel(Enum):
+ """Log severity level. Determines how the message is displayed in the timeline. Defaults to
+ "info".
+ """
+ ERROR = "error"
+ INFO = "info"
+ WARNING = "warning"
- ACCEPT = "accept"
- CANCEL = "cancel"
- DECLINE = "decline"
+@dataclass
+class ShellExecResult:
+ 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)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["processId"] = from_str(self.process_id)
+ return result
@dataclass
-class UIElicitationResponse:
- """The elicitation response (accept with form values, decline, or cancel)"""
+class ShellExecRequest:
+ command: str
+ """Shell command to execute"""
- action: UIElicitationResponseAction
- """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)"""
+ cwd: str | None = None
+ """Working directory (defaults to session working directory)"""
- content: dict[str, float | bool | list[str] | str] | None = None
- """The form values submitted by the user (present when action is 'accept')"""
+ timeout: int | None = None
+ """Timeout in milliseconds (default: 30000)"""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationResponse':
+ def from_dict(obj: Any) -> 'ShellExecRequest':
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)
+ 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["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["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
-class UIElicitationSchemaPropertyStringFormat(Enum):
- DATE = "date"
- DATE_TIME = "date-time"
- EMAIL = "email"
- URI = "uri"
-
@dataclass
-class UIElicitationArrayAnyOfFieldItemsAnyOf:
- const: str
- title: str
+class ShellKillResult:
+ killed: bool
+ """Whether the signal was sent successfully"""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItemsAnyOf':
+ def from_dict(obj: Any) -> 'ShellKillResult':
assert isinstance(obj, dict)
- const = from_str(obj.get("const"))
- title = from_str(obj.get("title"))
- return UIElicitationArrayAnyOfFieldItemsAnyOf(const, title)
+ killed = from_bool(obj.get("killed"))
+ return ShellKillResult(killed)
def to_dict(self) -> dict:
result: dict = {}
- result["const"] = from_str(self.const)
- result["title"] = from_str(self.title)
+ result["killed"] = from_bool(self.killed)
return result
-class ItemsType(Enum):
- STRING = "string"
+class ShellKillSignal(Enum):
+ """Signal to send (default: SIGTERM)"""
+
+ SIGINT = "SIGINT"
+ SIGKILL = "SIGKILL"
+ SIGTERM = "SIGTERM"
@dataclass
-class UIElicitationArrayFieldItems:
- enum: list[str] | None = None
- type: ItemsType | None = None
- any_of: list[UIElicitationArrayAnyOfFieldItemsAnyOf] | None = None
+class HistoryCompactContextWindow:
+ """Post-compaction context window usage breakdown"""
+
+ current_tokens: int
+ """Current total tokens in the context window (system + conversation + tool definitions)"""
+
+ messages_length: int
+ """Current number of messages in the conversation"""
+
+ token_limit: int
+ """Maximum token count for the model's context window"""
+
+ conversation_tokens: int | None = None
+ """Token count from non-system messages (user, assistant, tool)"""
+
+ system_tokens: int | None = None
+ """Token count from system message(s)"""
+
+ tool_definitions_tokens: int | None = None
+ """Token count from tool definitions"""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationArrayFieldItems':
+ def from_dict(obj: Any) -> 'HistoryCompactContextWindow':
assert isinstance(obj, dict)
- enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum"))
- type = from_union([ItemsType, from_none], obj.get("type"))
- any_of = from_union([lambda x: from_list(UIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf"))
- return UIElicitationArrayFieldItems(enum, type, any_of)
+ current_tokens = from_int(obj.get("currentTokens"))
+ messages_length = from_int(obj.get("messagesLength"))
+ token_limit = from_int(obj.get("tokenLimit"))
+ conversation_tokens = from_union([from_int, from_none], obj.get("conversationTokens"))
+ system_tokens = from_union([from_int, from_none], obj.get("systemTokens"))
+ tool_definitions_tokens = from_union([from_int, from_none], obj.get("toolDefinitionsTokens"))
+ return HistoryCompactContextWindow(current_tokens, messages_length, token_limit, conversation_tokens, system_tokens, tool_definitions_tokens)
def to_dict(self) -> dict:
result: dict = {}
- 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(ItemsType, x), from_none], self.type)
- if self.any_of is not None:
- result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of)
+ result["currentTokens"] = from_int(self.current_tokens)
+ result["messagesLength"] = from_int(self.messages_length)
+ result["tokenLimit"] = from_int(self.token_limit)
+ if self.conversation_tokens is not None:
+ result["conversationTokens"] = from_union([from_int, from_none], self.conversation_tokens)
+ if self.system_tokens is not None:
+ result["systemTokens"] = from_union([from_int, from_none], self.system_tokens)
+ if self.tool_definitions_tokens is not None:
+ 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 UIElicitationStringOneOfFieldOneOf:
- const: str
- title: str
+class HistoryTruncateResult:
+ events_removed: int
+ """Number of events that were removed"""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationStringOneOfFieldOneOf':
+ def from_dict(obj: Any) -> 'HistoryTruncateResult':
assert isinstance(obj, dict)
- const = from_str(obj.get("const"))
- title = from_str(obj.get("title"))
- return UIElicitationStringOneOfFieldOneOf(const, title)
+ events_removed = from_int(obj.get("eventsRemoved"))
+ return HistoryTruncateResult(events_removed)
def to_dict(self) -> dict:
result: dict = {}
- result["const"] = from_str(self.const)
- result["title"] = from_str(self.title)
+ result["eventsRemoved"] = from_int(self.events_removed)
return result
-class UIElicitationSchemaPropertyNumberType(Enum):
- ARRAY = "array"
- BOOLEAN = "boolean"
- INTEGER = "integer"
- NUMBER = "number"
- STRING = "string"
-
+# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class UIElicitationSchemaProperty:
- type: UIElicitationSchemaPropertyNumberType
- default: float | bool | list[str] | str | None = None
- description: str | None = None
- enum: list[str] | None = None
- enum_names: list[str] | None = None
- title: str | None = None
- one_of: list[UIElicitationStringOneOfFieldOneOf] | None = None
- items: UIElicitationArrayFieldItems | None = None
- max_items: float | None = None
- min_items: float | None = None
- format: UIElicitationSchemaPropertyStringFormat | None = None
- max_length: float | None = None
- min_length: float | None = None
- maximum: float | None = None
- minimum: float | None = None
+class HistoryTruncateRequest:
+ event_id: str
+ """Event ID to truncate to. This event and all events after it are removed from the session."""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationSchemaProperty':
+ def from_dict(obj: Any) -> 'HistoryTruncateRequest':
assert isinstance(obj, dict)
- type = UIElicitationSchemaPropertyNumberType(obj.get("type"))
- default = from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], obj.get("default"))
- description = from_union([from_str, from_none], obj.get("description"))
- enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum"))
- enum_names = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enumNames"))
- title = from_union([from_str, from_none], obj.get("title"))
- one_of = from_union([lambda x: from_list(UIElicitationStringOneOfFieldOneOf.from_dict, x), from_none], obj.get("oneOf"))
- items = from_union([UIElicitationArrayFieldItems.from_dict, from_none], obj.get("items"))
- max_items = from_union([from_float, from_none], obj.get("maxItems"))
- min_items = from_union([from_float, from_none], obj.get("minItems"))
- format = from_union([UIElicitationSchemaPropertyStringFormat, from_none], obj.get("format"))
- max_length = from_union([from_float, from_none], obj.get("maxLength"))
- min_length = from_union([from_float, from_none], obj.get("minLength"))
- maximum = from_union([from_float, from_none], obj.get("maximum"))
- minimum = from_union([from_float, from_none], obj.get("minimum"))
- return UIElicitationSchemaProperty(type, default, description, enum, enum_names, title, one_of, items, max_items, min_items, format, max_length, min_length, maximum, minimum)
+ event_id = from_str(obj.get("eventId"))
+ return HistoryTruncateRequest(event_id)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["eventId"] = from_str(self.event_id)
+ return result
+
+@dataclass
+class UsageMetricsCodeChanges:
+ """Aggregated code change metrics"""
+
+ files_modified_count: int
+ """Number of distinct files modified"""
+
+ lines_added: int
+ """Total lines of code added"""
+
+ lines_removed: int
+ """Total lines of code removed"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UsageMetricsCodeChanges':
+ assert isinstance(obj, dict)
+ files_modified_count = from_int(obj.get("filesModifiedCount"))
+ lines_added = from_int(obj.get("linesAdded"))
+ lines_removed = from_int(obj.get("linesRemoved"))
+ return UsageMetricsCodeChanges(files_modified_count, lines_added, lines_removed)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["filesModifiedCount"] = from_int(self.files_modified_count)
+ result["linesAdded"] = from_int(self.lines_added)
+ result["linesRemoved"] = from_int(self.lines_removed)
+ return result
+
+@dataclass
+class UsageMetricsModelMetricRequests:
+ """Request count and cost metrics for this model"""
+
+ cost: float
+ """User-initiated premium request cost (with multiplier applied)"""
+
+ count: int
+ """Number of API requests made with this model"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UsageMetricsModelMetricRequests':
+ assert isinstance(obj, dict)
+ cost = from_float(obj.get("cost"))
+ count = from_int(obj.get("count"))
+ return UsageMetricsModelMetricRequests(cost, count)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["cost"] = to_float(self.cost)
+ result["count"] = from_int(self.count)
+ return result
+
+@dataclass
+class UsageMetricsModelMetricUsage:
+ """Token usage metrics for this model"""
+
+ cache_read_tokens: int
+ """Total tokens read from prompt cache"""
+
+ cache_write_tokens: int
+ """Total tokens written to prompt cache"""
+
+ input_tokens: int
+ """Total input tokens consumed"""
+
+ output_tokens: int
+ """Total output tokens produced"""
+
+ reasoning_tokens: int | None = None
+ """Total output tokens used for reasoning"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UsageMetricsModelMetricUsage':
+ assert isinstance(obj, dict)
+ cache_read_tokens = from_int(obj.get("cacheReadTokens"))
+ cache_write_tokens = from_int(obj.get("cacheWriteTokens"))
+ input_tokens = from_int(obj.get("inputTokens"))
+ output_tokens = from_int(obj.get("outputTokens"))
+ reasoning_tokens = from_union([from_int, from_none], obj.get("reasoningTokens"))
+ return UsageMetricsModelMetricUsage(cache_read_tokens, cache_write_tokens, input_tokens, output_tokens, reasoning_tokens)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["cacheReadTokens"] = from_int(self.cache_read_tokens)
+ result["cacheWriteTokens"] = from_int(self.cache_write_tokens)
+ result["inputTokens"] = from_int(self.input_tokens)
+ result["outputTokens"] = from_int(self.output_tokens)
+ if self.reasoning_tokens is not None:
+ result["reasoningTokens"] = from_union([from_int, from_none], self.reasoning_tokens)
+ return result
+
+@dataclass
+class SessionFSReadFileResult:
+ content: str
+ """File content as UTF-8 string"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReadFileResult':
+ assert isinstance(obj, dict)
+ content = from_str(obj.get("content"))
+ return SessionFSReadFileResult(content)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["content"] = from_str(self.content)
+ return result
+
+@dataclass
+class SessionFSReadFileRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReadFileRequest':
+ assert isinstance(obj, dict)
+ 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["path"] = from_str(self.path)
+ result["sessionId"] = from_str(self.session_id)
+ return result
+
+@dataclass
+class SessionFSWriteFileRequest:
+ content: str
+ """Content to write"""
+
+ 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) -> 'SessionFSWriteFileRequest':
+ assert isinstance(obj, dict)
+ content = from_str(obj.get("content"))
+ path = from_str(obj.get("path"))
+ session_id = from_str(obj.get("sessionId"))
+ mode = from_union([from_int, from_none], obj.get("mode"))
+ return SessionFSWriteFileRequest(content, path, session_id, mode)
+
+ 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
+
+@dataclass
+class SessionFSAppendFileRequest:
+ content: str
+ """Content to append"""
+
+ 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) -> 'SessionFSAppendFileRequest':
+ assert isinstance(obj, dict)
+ content = from_str(obj.get("content"))
+ path = from_str(obj.get("path"))
+ session_id = from_str(obj.get("sessionId"))
+ mode = from_union([from_int, from_none], obj.get("mode"))
+ return SessionFSAppendFileRequest(content, path, session_id, mode)
+
+ 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
+
+@dataclass
+class SessionFSExistsResult:
+ exists: bool
+ """Whether the path exists"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSExistsResult':
+ assert isinstance(obj, dict)
+ exists = from_bool(obj.get("exists"))
+ return SessionFSExistsResult(exists)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["exists"] = from_bool(self.exists)
+ return result
+
+@dataclass
+class SessionFSExistsRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSExistsRequest':
+ assert isinstance(obj, dict)
+ 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["path"] = from_str(self.path)
+ result["sessionId"] = from_str(self.session_id)
+ return result
+
+@dataclass
+class SessionFSStatResult:
+ birthtime: datetime
+ """ISO 8601 timestamp of creation"""
+
+ is_directory: bool
+ """Whether the path is a directory"""
+
+ is_file: bool
+ """Whether the path is a file"""
+
+ mtime: datetime
+ """ISO 8601 timestamp of last modification"""
+
+ size: int
+ """File size in bytes"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSStatResult':
+ assert isinstance(obj, dict)
+ birthtime = from_datetime(obj.get("birthtime"))
+ is_directory = from_bool(obj.get("isDirectory"))
+ is_file = from_bool(obj.get("isFile"))
+ mtime = from_datetime(obj.get("mtime"))
+ size = from_int(obj.get("size"))
+ return SessionFSStatResult(birthtime, is_directory, is_file, mtime, size)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["birthtime"] = self.birthtime.isoformat()
+ result["isDirectory"] = from_bool(self.is_directory)
+ result["isFile"] = from_bool(self.is_file)
+ result["mtime"] = self.mtime.isoformat()
+ result["size"] = from_int(self.size)
+ return result
+
+@dataclass
+class SessionFSStatRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSStatRequest':
+ assert isinstance(obj, dict)
+ 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["path"] = from_str(self.path)
+ result["sessionId"] = from_str(self.session_id)
+ return result
+
+@dataclass
+class SessionFSMkdirRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ mode: int | None = None
+ """Optional POSIX-style mode for newly created directories"""
+
+ recursive: bool | None = None
+ """Create parent directories as needed"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSMkdirRequest':
+ 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)
+
+ 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)
+ return result
+
+@dataclass
+class SessionFSReaddirResult:
+ entries: list[str]
+ """Entry names in the directory"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReaddirResult':
+ assert isinstance(obj, dict)
+ entries = from_list(from_str, obj.get("entries"))
+ return SessionFSReaddirResult(entries)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["entries"] = from_list(from_str, self.entries)
+ return result
+
+@dataclass
+class SessionFSReaddirRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReaddirRequest':
+ assert isinstance(obj, dict)
+ 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["path"] = from_str(self.path)
+ result["sessionId"] = from_str(self.session_id)
+ return result
+
+class SessionFSReaddirWithTypesEntryType(Enum):
+ """Entry type"""
+
+ DIRECTORY = "directory"
+ FILE = "file"
+
+@dataclass
+class SessionFSReaddirWithTypesRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesRequest':
+ assert isinstance(obj, dict)
+ 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 = {}
+ result["path"] = from_str(self.path)
+ result["sessionId"] = from_str(self.session_id)
+ return result
+
+@dataclass
+class SessionFSRmRequest:
+ path: str
+ """Path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ 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) -> 'SessionFSRmRequest':
+ assert isinstance(obj, dict)
+ path = from_str(obj.get("path"))
+ session_id = from_str(obj.get("sessionId"))
+ force = from_union([from_bool, from_none], obj.get("force"))
+ recursive = from_union([from_bool, from_none], obj.get("recursive"))
+ return SessionFSRmRequest(path, session_id, force, recursive)
+
+ 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)
+ return result
+
+@dataclass
+class SessionFSRenameRequest:
+ dest: str
+ """Destination path using SessionFs conventions"""
+
+ session_id: str
+ """Target session identifier"""
+
+ src: str
+ """Source path using SessionFs conventions"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSRenameRequest':
+ assert isinstance(obj, dict)
+ dest = from_str(obj.get("dest"))
+ session_id = from_str(obj.get("sessionId"))
+ src = from_str(obj.get("src"))
+ return SessionFSRenameRequest(dest, session_id, src)
+
+ 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)
+ 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: PurpleModelCapabilitiesLimitsVision | 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([PurpleModelCapabilitiesLimitsVision.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(PurpleModelCapabilitiesLimitsVision, x), from_none], self.vision)
+ return result
+
+@dataclass
+class MCPServerConfig:
+ """MCP server configuration (local/stdio or remote/http)"""
+
+ args: list[str] | None = None
+ command: str | None = None
+ cwd: str | None = None
+ env: dict[str, str] | None = None
+ filter_mapping: dict[str, FilterMappingString] | FilterMappingString | None = None
+ is_default_server: bool | None = None
+ timeout: int | None = None
+ """Timeout in milliseconds for tool calls to this server."""
+
+ tools: list[str] | None = None
+ """Tools to include. Defaults to all tools if not specified."""
+
+ type: MCPServerConfigType | None = None
+ """Remote transport type. Defaults to "http" when omitted."""
+
+ headers: dict[str, str] | None = None
+ oauth_client_id: str | None = None
+ oauth_public_client: bool | None = None
+ url: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> '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(FilterMappingString, x), FilterMappingString, 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"))
+ type = from_union([MCPServerConfigType, from_none], obj.get("type"))
+ headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
+ oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
+ oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
+ url = from_union([from_str, from_none], obj.get("url"))
+ return MCPServerConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ 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(FilterMappingString, x), x), lambda x: to_enum(FilterMappingString, 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.type is not None:
+ result["type"] = from_union([lambda x: to_enum(MCPServerConfigType, x), from_none], self.type)
+ if self.headers is not None:
+ result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
+ if self.oauth_client_id is not None:
+ result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
+ if self.oauth_public_client is not None:
+ result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
+ if self.url is not None:
+ result["url"] = from_union([from_str, from_none], self.url)
+ return result
+
+@dataclass
+class MCPServerConfigValue:
+ """MCP server configuration (local/stdio or remote/http)"""
+
+ args: list[str] | None = None
+ command: str | None = None
+ cwd: str | None = None
+ env: dict[str, str] | None = None
+ filter_mapping: dict[str, FilterMappingString] | FilterMappingString | None = None
+ is_default_server: bool | None = None
+ timeout: int | None = None
+ """Timeout in milliseconds for tool calls to this server."""
+
+ tools: list[str] | None = None
+ """Tools to include. Defaults to all tools if not specified."""
+
+ type: MCPServerConfigType | None = None
+ """Remote transport type. Defaults to "http" when omitted."""
+
+ headers: dict[str, str] | None = None
+ oauth_client_id: str | None = None
+ oauth_public_client: bool | None = None
+ url: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'MCPServerConfigValue':
+ 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(FilterMappingString, x), FilterMappingString, 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"))
+ type = from_union([MCPServerConfigType, from_none], obj.get("type"))
+ headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
+ oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
+ oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
+ url = from_union([from_str, from_none], obj.get("url"))
+ return MCPServerConfigValue(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ 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(FilterMappingString, x), x), lambda x: to_enum(FilterMappingString, 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.type is not None:
+ result["type"] = from_union([lambda x: to_enum(MCPServerConfigType, x), from_none], self.type)
+ if self.headers is not None:
+ result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
+ if self.oauth_client_id is not None:
+ result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
+ if self.oauth_public_client is not None:
+ result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
+ if self.url is not None:
+ result["url"] = from_union([from_str, from_none], self.url)
+ return result
+
+@dataclass
+class MCPConfigAddRequestMCPServerConfig:
+ """MCP server configuration (local/stdio or remote/http)"""
+
+ args: list[str] | None = None
+ command: str | None = None
+ cwd: str | None = None
+ env: dict[str, str] | None = None
+ filter_mapping: dict[str, FilterMappingString] | FilterMappingString | None = None
+ is_default_server: bool | None = None
+ timeout: int | None = None
+ """Timeout in milliseconds for tool calls to this server."""
+
+ tools: list[str] | None = None
+ """Tools to include. Defaults to all tools if not specified."""
+
+ type: MCPServerConfigType | None = None
+ """Remote transport type. Defaults to "http" when omitted."""
+
+ headers: dict[str, str] | None = None
+ oauth_client_id: str | None = None
+ oauth_public_client: bool | None = None
+ url: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'MCPConfigAddRequestMCPServerConfig':
+ 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(FilterMappingString, x), FilterMappingString, 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"))
+ type = from_union([MCPServerConfigType, from_none], obj.get("type"))
+ headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
+ oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
+ oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
+ url = from_union([from_str, from_none], obj.get("url"))
+ return MCPConfigAddRequestMCPServerConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ 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(FilterMappingString, x), x), lambda x: to_enum(FilterMappingString, 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.type is not None:
+ result["type"] = from_union([lambda x: to_enum(MCPServerConfigType, x), from_none], self.type)
+ if self.headers is not None:
+ result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
+ if self.oauth_client_id is not None:
+ result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
+ if self.oauth_public_client is not None:
+ result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
+ if self.url is not None:
+ result["url"] = from_union([from_str, from_none], self.url)
+ return result
+
+@dataclass
+class MCPConfigUpdateRequestMCPServerConfig:
+ """MCP server configuration (local/stdio or remote/http)"""
+
+ args: list[str] | None = None
+ command: str | None = None
+ cwd: str | None = None
+ env: dict[str, str] | None = None
+ filter_mapping: dict[str, FilterMappingString] | FilterMappingString | None = None
+ is_default_server: bool | None = None
+ timeout: int | None = None
+ """Timeout in milliseconds for tool calls to this server."""
+
+ tools: list[str] | None = None
+ """Tools to include. Defaults to all tools if not specified."""
+
+ type: MCPServerConfigType | None = None
+ """Remote transport type. Defaults to "http" when omitted."""
+
+ headers: dict[str, str] | None = None
+ oauth_client_id: str | None = None
+ oauth_public_client: bool | None = None
+ url: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'MCPConfigUpdateRequestMCPServerConfig':
+ 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(FilterMappingString, x), FilterMappingString, 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"))
+ type = from_union([MCPServerConfigType, from_none], obj.get("type"))
+ headers = from_union([lambda x: from_dict(from_str, x), from_none], obj.get("headers"))
+ oauth_client_id = from_union([from_str, from_none], obj.get("oauthClientId"))
+ oauth_public_client = from_union([from_bool, from_none], obj.get("oauthPublicClient"))
+ url = from_union([from_str, from_none], obj.get("url"))
+ return MCPConfigUpdateRequestMCPServerConfig(args, command, cwd, env, filter_mapping, is_default_server, timeout, tools, type, headers, oauth_client_id, oauth_public_client, url)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ 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(FilterMappingString, x), x), lambda x: to_enum(FilterMappingString, 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.type is not None:
+ result["type"] = from_union([lambda x: to_enum(MCPServerConfigType, x), from_none], self.type)
+ if self.headers is not None:
+ result["headers"] = from_union([lambda x: from_dict(from_str, x), from_none], self.headers)
+ if self.oauth_client_id is not None:
+ result["oauthClientId"] = from_union([from_str, from_none], self.oauth_client_id)
+ if self.oauth_public_client is not None:
+ result["oauthPublicClient"] = from_union([from_bool, from_none], self.oauth_public_client)
+ if self.url is not None:
+ result["url"] = from_union([from_str, from_none], self.url)
+ return result
+
+@dataclass
+class DiscoveredMCPServer:
+ enabled: bool
+ """Whether the server is enabled (not in the disabled list)"""
+
+ name: str
+ """Server name (config key)"""
+
+ source: MCPServerSource
+ """Configuration source"""
+
+ type: DiscoveredMCPServerType | None = None
+ """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'DiscoveredMCPServer':
+ 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
+
+@dataclass
+class ServerElement:
+ enabled: bool
+ """Whether the server is enabled (not in the disabled list)"""
+
+ name: str
+ """Server name (config key)"""
+
+ source: MCPServerSource
+ """Configuration source"""
+
+ type: DiscoveredMCPServerType | None = None
+ """Server transport type: stdio, http, sse, or memory (local configs are normalized to stdio)"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ServerElement':
+ 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 ServerElement(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
+
+@dataclass
+class ServerSkillList:
+ skills: list[SkillElement]
+ """All discovered skills across all sources"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ServerSkillList':
+ assert isinstance(obj, dict)
+ skills = from_list(SkillElement.from_dict, obj.get("skills"))
+ return ServerSkillList(skills)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["skills"] = from_list(lambda x: to_class(SkillElement, x), self.skills)
+ 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
+ max_prompt_tokens: int | None = None
+ vision: PurpleModelCapabilitiesOverrideLimitsVision | None = None
+
+ @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([PurpleModelCapabilitiesOverrideLimitsVision.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(PurpleModelCapabilitiesOverrideLimitsVision, x), from_none], self.vision)
+ return result
+
+@dataclass
+class MCPServer:
+ name: str
+ """Server name (config key)"""
+
+ status: MCPServerStatus
+ """Connection status: connected, failed, needs-auth, pending, disabled, or not_configured"""
+
+ error: str | None = None
+ """Error message if the server failed to connect"""
+
+ source: MCPServerSource | None = None
+ """Configuration source: user, workspace, plugin, or builtin"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'MCPServer':
+ assert isinstance(obj, dict)
+ name = from_str(obj.get("name"))
+ status = MCPServerStatus(obj.get("status"))
+ error = from_union([from_str, from_none], obj.get("error"))
+ source = from_union([MCPServerSource, from_none], obj.get("source"))
+ return MCPServer(name, status, error, source)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["name"] = from_str(self.name)
+ result["status"] = to_enum(MCPServerStatus, self.status)
+ if self.error is not None:
+ result["error"] = from_union([from_str, from_none], self.error)
+ if self.source is not None:
+ result["source"] = from_union([lambda x: to_enum(MCPServerSource, x), from_none], self.source)
+ return result
+
+@dataclass
+class UIElicitationStringEnumField:
+ enum: list[str]
+ type: UIElicitationStringEnumFieldType
+ default: str | None = None
+ description: str | None = None
+ enum_names: list[str] | None = None
+ title: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationStringEnumField':
+ assert isinstance(obj, dict)
+ enum = from_list(from_str, obj.get("enum"))
+ type = UIElicitationStringEnumFieldType(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["enum"] = from_list(from_str, self.enum)
+ result["type"] = to_enum(UIElicitationStringEnumFieldType, 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 UIElicitationArrayEnumFieldItems:
+ enum: list[str]
+ type: UIElicitationStringEnumFieldType
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationArrayEnumFieldItems':
+ assert isinstance(obj, dict)
+ enum = from_list(from_str, obj.get("enum"))
+ type = UIElicitationStringEnumFieldType(obj.get("type"))
+ return UIElicitationArrayEnumFieldItems(enum, type)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["enum"] = from_list(from_str, self.enum)
+ result["type"] = to_enum(UIElicitationStringEnumFieldType, self.type)
+ return result
+
+@dataclass
+class UIElicitationStringOneOfField:
+ one_of: list[UIElicitationStringOneOfFieldOneOf]
+ type: UIElicitationStringEnumFieldType
+ default: str | None = None
+ description: str | None = None
+ title: str | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationStringOneOfField':
+ assert isinstance(obj, dict)
+ one_of = from_list(UIElicitationStringOneOfFieldOneOf.from_dict, obj.get("oneOf"))
+ type = UIElicitationStringEnumFieldType(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["oneOf"] = from_list(lambda x: to_class(UIElicitationStringOneOfFieldOneOf, x), self.one_of)
+ result["type"] = to_enum(UIElicitationStringEnumFieldType, 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 UIElicitationArrayAnyOfFieldItems:
+ any_of: list[PurpleUIElicitationArrayAnyOfFieldItemsAnyOf]
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfFieldItems':
+ assert isinstance(obj, dict)
+ any_of = from_list(PurpleUIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, obj.get("anyOf"))
+ return UIElicitationArrayAnyOfFieldItems(any_of)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["anyOf"] = from_list(lambda x: to_class(PurpleUIElicitationArrayAnyOfFieldItemsAnyOf, x), self.any_of)
+ return result
+
+@dataclass
+class UIElicitationResponse:
+ """The elicitation response (accept with form values, decline, or cancel)"""
+
+ action: UIElicitationResponseAction
+ """The user's response: accept (submitted), decline (rejected), or cancel (dismissed)"""
+
+ content: dict[str, float | bool | list[str] | str] | None = None
+ """The form values submitted by the user (present when action is 'accept')"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationResponse':
+ 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)
+
+ 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)
+ return result
+
+@dataclass
+class PermissionDecision:
+ kind: Kind
+ """The permission request was approved
+
+ Denied because approval rules explicitly blocked it
+
+ Denied because no approval rule matched and user confirmation was unavailable
+
+ Denied by the user during an interactive prompt
+
+ Denied by the organization's content exclusion policy
+
+ Denied by a permission request hook registered by an extension or plugin
+ """
+ rules: list[Any] | None = None
+ """Rules that denied the request"""
+
+ feedback: str | None = None
+ """Optional feedback from the user explaining the denial"""
+
+ message: str | None = None
+ """Human-readable explanation of why the path was excluded
+
+ Optional message from the hook explaining the denial
+ """
+ path: str | None = None
+ """File path that triggered the exclusion"""
+
+ interrupt: bool | None = None
+ """Whether to interrupt the current agent turn"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'PermissionDecision':
+ assert isinstance(obj, dict)
+ kind = Kind(obj.get("kind"))
+ rules = from_union([lambda x: from_list(lambda x: x, x), from_none], obj.get("rules"))
+ feedback = from_union([from_str, from_none], obj.get("feedback"))
+ message = from_union([from_str, from_none], obj.get("message"))
+ path = from_union([from_str, from_none], obj.get("path"))
+ interrupt = from_union([from_bool, from_none], obj.get("interrupt"))
+ return PermissionDecision(kind, rules, feedback, message, path, interrupt)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["kind"] = to_enum(Kind, self.kind)
+ if self.rules is not None:
+ result["rules"] = from_union([lambda x: from_list(lambda x: x, x), from_none], self.rules)
+ if self.feedback is not None:
+ result["feedback"] = from_union([from_str, from_none], self.feedback)
+ 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
+class CapabilitiesLimits:
+ """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: FluffyModelCapabilitiesLimitsVision | None = None
+ """Vision-specific limits"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'CapabilitiesLimits':
+ 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([FluffyModelCapabilitiesLimitsVision.from_dict, from_none], obj.get("vision"))
+ return CapabilitiesLimits(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(FluffyModelCapabilitiesLimitsVision, x), from_none], self.vision)
+ return result
+
+@dataclass
+class ToolList:
+ tools: list[Tool]
+ """List of available built-in tools with metadata"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ToolList':
+ assert isinstance(obj, dict)
+ tools = from_list(Tool.from_dict, obj.get("tools"))
+ return ToolList(tools)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["tools"] = from_list(lambda x: to_class(Tool, x), self.tools)
+ return result
+
+@dataclass
+class ToolsHandlePendingToolCallRequest:
+ request_id: str
+ """Request ID of the pending tool call"""
+
+ error: str | None = None
+ """Error message if the tool call failed"""
+
+ result: ToolCallResult | str | None = None
+ """Tool call result (string or expanded result object)"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ToolsHandlePendingToolCallRequest':
+ assert isinstance(obj, dict)
+ request_id = from_str(obj.get("requestId"))
+ error = from_union([from_str, from_none], obj.get("error"))
+ result = from_union([ToolCallResult.from_dict, from_str, from_none], obj.get("result"))
+ return ToolsHandlePendingToolCallRequest(request_id, error, result)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["requestId"] = from_str(self.request_id)
+ if self.error is not None:
+ result["error"] = from_union([from_str, from_none], self.error)
+ if self.result is not None:
+ result["result"] = from_union([lambda x: to_class(ToolCallResult, x), from_str, from_none], self.result)
+ return result
+
+@dataclass
+class AccountGetQuotaResult:
+ 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["type"] = to_enum(UIElicitationSchemaPropertyNumberType, self.type)
- if self.default is not None:
- result["default"] = from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], self.default)
+ result["quotaSnapshots"] = from_dict(lambda x: to_class(AccountQuotaSnapshot, x), self.quota_snapshots)
+ return result
+
+@dataclass
+class SessionFSSetProviderRequest:
+ conventions: SessionFSSetProviderConventions
+ """Path conventions used by this filesystem"""
+
+ initial_cwd: str
+ """Initial working directory for sessions"""
+
+ session_state_path: str
+ """Path within each session's SessionFs where the runtime stores files for that session"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSSetProviderRequest':
+ assert isinstance(obj, dict)
+ conventions = SessionFSSetProviderConventions(obj.get("conventions"))
+ initial_cwd = from_str(obj.get("initialCwd"))
+ session_state_path = from_str(obj.get("sessionStatePath"))
+ return SessionFSSetProviderRequest(conventions, initial_cwd, session_state_path)
+
+ 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)
+ return result
+
+@dataclass
+class ModelCapabilitiesLimitsClass:
+ """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
+ max_prompt_tokens: int | None = None
+ vision: FluffyModelCapabilitiesOverrideLimitsVision | None = None
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ModelCapabilitiesLimitsClass':
+ 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([FluffyModelCapabilitiesOverrideLimitsVision.from_dict, from_none], obj.get("vision"))
+ return ModelCapabilitiesLimitsClass(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(FluffyModelCapabilitiesOverrideLimitsVision, x), from_none], self.vision)
+ return result
+
+@dataclass
+class ModeSetRequest:
+ mode: SessionMode
+ """The agent mode. Valid values: "interactive", "plan", "autopilot"."""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'ModeSetRequest':
+ assert isinstance(obj, dict)
+ mode = SessionMode(obj.get("mode"))
+ return ModeSetRequest(mode)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["mode"] = to_enum(SessionMode, self.mode)
+ 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
+ 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
+ pr_create_sync_dismissed: bool | None = None
+ repository: str | None = None
+ session_sync_level: SessionSyncLevel | None = None
+ summary: str | None = None
+ summary_count: int | None = None
+ updated_at: datetime | 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([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"))
+ pr_create_sync_dismissed = from_union([from_bool, from_none], obj.get("pr_create_sync_dismissed"))
+ repository = from_union([from_str, from_none], obj.get("repository"))
+ session_sync_level = from_union([SessionSyncLevel, from_none], obj.get("session_sync_level"))
+ summary = from_union([from_str, from_none], obj.get("summary"))
+ summary_count = from_union([from_int, from_none], obj.get("summary_count"))
+ updated_at = from_union([from_datetime, from_none], obj.get("updated_at"))
+ 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, pr_create_sync_dismissed, repository, session_sync_level, summary, summary_count, updated_at)
+
+ 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.pr_create_sync_dismissed is not None:
+ result["pr_create_sync_dismissed"] = from_union([from_bool, from_none], self.pr_create_sync_dismissed)
+ if self.repository is not None:
+ result["repository"] = from_union([from_str, from_none], self.repository)
+ if self.session_sync_level is not None:
+ result["session_sync_level"] = from_union([lambda x: to_enum(SessionSyncLevel, x), from_none], self.session_sync_level)
+ if self.summary is not None:
+ result["summary"] = from_union([from_str, from_none], self.summary)
+ 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)
+ return result
+
+@dataclass
+class InstructionsSources:
+ 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: str | None = None
+ """Glob pattern from frontmatter — when set, this instruction applies only to matching files"""
+
+ 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([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)
+
+ 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)
- if self.enum is not None:
- result["enum"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum)
- 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)
- if self.one_of is not None:
- result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationStringOneOfFieldOneOf, x), x), from_none], self.one_of)
- if self.items is not None:
- result["items"] = from_union([lambda x: to_class(UIElicitationArrayFieldItems, x), from_none], self.items)
- if self.max_items is not None:
- result["maxItems"] = from_union([to_float, from_none], self.max_items)
- if self.min_items is not None:
- result["minItems"] = from_union([to_float, from_none], self.min_items)
- if self.format is not None:
- result["format"] = from_union([lambda x: to_enum(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.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)
return result
-class RequestedSchemaType(Enum):
- OBJECT = "object"
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class AgentList:
+ agents: list[AgentListAgent]
+ """Available custom agents"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'AgentList':
+ assert isinstance(obj, dict)
+ agents = from_list(AgentListAgent.from_dict, obj.get("agents"))
+ return AgentList(agents)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["agents"] = from_list(lambda x: to_class(AgentListAgent, x), self.agents)
+ return result
+
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class AgentSelectResult:
+ agent: AgentSelectResultAgent
+ """The newly selected custom agent"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'AgentSelectResult':
+ assert isinstance(obj, dict)
+ agent = AgentSelectResultAgent.from_dict(obj.get("agent"))
+ return AgentSelectResult(agent)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["agent"] = to_class(AgentSelectResultAgent, self.agent)
+ return result
+
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class AgentGetCurrentResult:
+ agent: AgentReloadResultAgent | 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([AgentReloadResultAgent.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(AgentReloadResultAgent, x), from_none], self.agent)
+ return result
+
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class AgentReloadResult:
+ agents: list[AgentReloadResultAgent]
+ """Reloaded custom agents"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'AgentReloadResult':
+ assert isinstance(obj, dict)
+ agents = from_list(AgentReloadResultAgent.from_dict, obj.get("agents"))
+ return AgentReloadResult(agents)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["agents"] = from_list(lambda x: to_class(AgentReloadResultAgent, x), self.agents)
+ return result
+# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class UIElicitationSchema:
- """JSON Schema describing the form fields to present to the user"""
+class SkillList:
+ skills: list[Skill]
+ """Available skills"""
- properties: dict[str, UIElicitationSchemaProperty]
- """Form field definitions, keyed by field name"""
+ @staticmethod
+ def from_dict(obj: Any) -> 'SkillList':
+ assert isinstance(obj, dict)
+ skills = from_list(Skill.from_dict, obj.get("skills"))
+ return SkillList(skills)
- type: RequestedSchemaType
- """Schema type indicator (always 'object')"""
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["skills"] = from_list(lambda x: to_class(Skill, x), self.skills)
+ return result
- required: list[str] | None = None
- """List of required field names"""
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class PluginList:
+ plugins: list[Plugin]
+ """Installed plugins"""
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationSchema':
+ def from_dict(obj: Any) -> 'PluginList':
assert isinstance(obj, dict)
- properties = from_dict(UIElicitationSchemaProperty.from_dict, obj.get("properties"))
- type = RequestedSchemaType(obj.get("type"))
- required = from_union([lambda x: from_list(from_str, x), from_none], obj.get("required"))
- return UIElicitationSchema(properties, type, required)
+ plugins = from_list(Plugin.from_dict, obj.get("plugins"))
+ return PluginList(plugins)
def to_dict(self) -> dict:
result: dict = {}
- result["properties"] = from_dict(lambda x: to_class(UIElicitationSchemaProperty, x), self.properties)
- result["type"] = to_enum(RequestedSchemaType, self.type)
- if self.required is not None:
- result["required"] = from_union([lambda x: from_list(from_str, x), from_none], self.required)
+ result["plugins"] = from_list(lambda x: to_class(Plugin, x), self.plugins)
return result
@dataclass
-class UIElicitationRequest:
- message: str
- """Message describing what information is needed from the user"""
+class Extension:
+ id: str
+ """Source-qualified ID (e.g., 'project:my-ext', 'user:auth-helper')"""
- requested_schema: UIElicitationSchema
- """JSON Schema describing the form fields to present to the user"""
+ 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) -> 'UIElicitationRequest':
+ def from_dict(obj: Any) -> 'Extension':
assert isinstance(obj, dict)
- message = from_str(obj.get("message"))
- requested_schema = UIElicitationSchema.from_dict(obj.get("requestedSchema"))
- return UIElicitationRequest(message, requested_schema)
+ 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["message"] = from_str(self.message)
- result["requestedSchema"] = to_class(UIElicitationSchema, self.requested_schema)
+ 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 UIElicitationResult:
- success: bool
- """Whether the response was accepted. False if the request was already resolved by another
- client.
- """
+class UIElicitationArrayFieldItems:
+ enum: list[str] | None = None
+ type: UIElicitationStringEnumFieldType | None = None
+ any_of: list[FluffyUIElicitationArrayAnyOfFieldItemsAnyOf] | None = None
@staticmethod
- def from_dict(obj: Any) -> 'UIElicitationResult':
+ def from_dict(obj: Any) -> 'UIElicitationArrayFieldItems':
assert isinstance(obj, dict)
- success = from_bool(obj.get("success"))
- return UIElicitationResult(success)
+ enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum"))
+ type = from_union([UIElicitationStringEnumFieldType, from_none], obj.get("type"))
+ any_of = from_union([lambda x: from_list(FluffyUIElicitationArrayAnyOfFieldItemsAnyOf.from_dict, x), from_none], obj.get("anyOf"))
+ return UIElicitationArrayFieldItems(enum, type, any_of)
def to_dict(self) -> dict:
result: dict = {}
- result["success"] = from_bool(self.success)
+ 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(UIElicitationStringEnumFieldType, x), from_none], self.type)
+ if self.any_of is not None:
+ result["anyOf"] = from_union([lambda x: from_list(lambda x: to_class(FluffyUIElicitationArrayAnyOfFieldItemsAnyOf, x), x), from_none], self.any_of)
return result
@dataclass
-class UIHandlePendingElicitationRequest:
- request_id: str
- """The unique request ID from the elicitation.requested event"""
+class LogRequest:
+ message: str
+ """Human-readable message"""
- result: UIElicitationResponse
- """The elicitation response (accept with form values, decline, or cancel)"""
+ 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".
+ """
+ url: str | None = None
+ """Optional URL the user can open in their browser for more details"""
@staticmethod
- def from_dict(obj: Any) -> 'UIHandlePendingElicitationRequest':
+ def from_dict(obj: Any) -> 'LogRequest':
assert isinstance(obj, dict)
- request_id = from_str(obj.get("requestId"))
- result = UIElicitationResponse.from_dict(obj.get("result"))
- return UIHandlePendingElicitationRequest(request_id, result)
+ 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)
def to_dict(self) -> dict:
result: dict = {}
- result["requestId"] = from_str(self.request_id)
- result["result"] = to_class(UIElicitationResponse, self.result)
+ 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)
return result
@dataclass
-class PermissionRequestResult:
- success: bool
- """Whether the permission request was handled successfully"""
+class ShellKillRequest:
+ process_id: str
+ """Process identifier returned by shell.exec"""
+
+ signal: ShellKillSignal | None = None
+ """Signal to send (default: SIGTERM)"""
@staticmethod
- def from_dict(obj: Any) -> 'PermissionRequestResult':
+ def from_dict(obj: Any) -> 'ShellKillRequest':
assert isinstance(obj, dict)
- success = from_bool(obj.get("success"))
- return PermissionRequestResult(success)
+ 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["success"] = from_bool(self.success)
+ 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
-class Kind(Enum):
- APPROVED = "approved"
- DENIED_BY_CONTENT_EXCLUSION_POLICY = "denied-by-content-exclusion-policy"
- DENIED_BY_PERMISSION_REQUEST_HOOK = "denied-by-permission-request-hook"
- DENIED_BY_RULES = "denied-by-rules"
- DENIED_INTERACTIVELY_BY_USER = "denied-interactively-by-user"
- DENIED_NO_APPROVAL_RULE_AND_COULD_NOT_REQUEST_FROM_USER = "denied-no-approval-rule-and-could-not-request-from-user"
-
+# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class PermissionDecision:
- kind: Kind
- """The permission request was approved
-
- Denied because approval rules explicitly blocked it
-
- Denied because no approval rule matched and user confirmation was unavailable
+class HistoryCompactResult:
+ messages_removed: int
+ """Number of messages removed during compaction"""
- Denied by the user during an interactive prompt
+ success: bool
+ """Whether compaction completed successfully"""
- Denied by the organization's content exclusion policy
+ tokens_removed: int
+ """Number of tokens freed by compaction"""
- Denied by a permission request hook registered by an extension or plugin
- """
- rules: list[Any] | None = None
- """Rules that denied the request"""
+ context_window: HistoryCompactContextWindow | None = None
+ """Post-compaction context window usage breakdown"""
- feedback: str | None = None
- """Optional feedback from the user explaining the denial"""
+ @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"))
+ return HistoryCompactResult(messages_removed, success, tokens_removed, context_window)
- message: str | None = None
- """Human-readable explanation of why the path was excluded
+ 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
- Optional message from the hook explaining the denial
- """
- path: str | None = None
- """File path that triggered the exclusion"""
+@dataclass
+class UsageMetricsModelMetric:
+ requests: UsageMetricsModelMetricRequests
+ """Request count and cost metrics for this model"""
- interrupt: bool | None = None
- """Whether to interrupt the current agent turn"""
+ usage: UsageMetricsModelMetricUsage
+ """Token usage metrics for this model"""
@staticmethod
- def from_dict(obj: Any) -> 'PermissionDecision':
+ def from_dict(obj: Any) -> 'UsageMetricsModelMetric':
assert isinstance(obj, dict)
- kind = Kind(obj.get("kind"))
- rules = from_union([lambda x: from_list(lambda x: x, x), from_none], obj.get("rules"))
- feedback = from_union([from_str, from_none], obj.get("feedback"))
- message = from_union([from_str, from_none], obj.get("message"))
- path = from_union([from_str, from_none], obj.get("path"))
- interrupt = from_union([from_bool, from_none], obj.get("interrupt"))
- return PermissionDecision(kind, rules, feedback, message, path, interrupt)
+ requests = UsageMetricsModelMetricRequests.from_dict(obj.get("requests"))
+ usage = UsageMetricsModelMetricUsage.from_dict(obj.get("usage"))
+ return UsageMetricsModelMetric(requests, usage)
def to_dict(self) -> dict:
result: dict = {}
- result["kind"] = to_enum(Kind, self.kind)
- if self.rules is not None:
- result["rules"] = from_union([lambda x: from_list(lambda x: x, x), from_none], self.rules)
- if self.feedback is not None:
- result["feedback"] = from_union([from_str, from_none], self.feedback)
- 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)
+ result["requests"] = to_class(UsageMetricsModelMetricRequests, self.requests)
+ result["usage"] = to_class(UsageMetricsModelMetricUsage, self.usage)
return result
@dataclass
-class PermissionDecisionRequest:
- request_id: str
- """Request ID of the pending permission request"""
+class SessionFSReaddirWithTypesEntry:
+ name: str
+ """Entry name"""
- result: PermissionDecision
+ type: SessionFSReaddirWithTypesEntryType
+ """Entry type"""
@staticmethod
- def from_dict(obj: Any) -> 'PermissionDecisionRequest':
+ def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry':
assert isinstance(obj, dict)
- request_id = from_str(obj.get("requestId"))
- result = PermissionDecision.from_dict(obj.get("result"))
- return PermissionDecisionRequest(request_id, result)
+ name = from_str(obj.get("name"))
+ type = SessionFSReaddirWithTypesEntryType(obj.get("type"))
+ return SessionFSReaddirWithTypesEntry(name, type)
def to_dict(self) -> dict:
result: dict = {}
- result["requestId"] = from_str(self.request_id)
- result["result"] = to_class(PermissionDecision, self.result)
+ result["name"] = from_str(self.name)
+ result["type"] = to_enum(SessionFSReaddirWithTypesEntryType, self.type)
return result
@dataclass
-class LogResult:
- event_id: UUID
- """The unique identifier of the emitted session event"""
+class MCPConfigList:
+ servers: dict[str, MCPServerConfigValue]
+ """All MCP servers from user config, keyed by name"""
@staticmethod
- def from_dict(obj: Any) -> 'LogResult':
+ def from_dict(obj: Any) -> 'MCPConfigList':
assert isinstance(obj, dict)
- event_id = UUID(obj.get("eventId"))
- return LogResult(event_id)
+ servers = from_dict(MCPServerConfigValue.from_dict, obj.get("servers"))
+ return MCPConfigList(servers)
def to_dict(self) -> dict:
result: dict = {}
- result["eventId"] = str(self.event_id)
+ result["servers"] = from_dict(lambda x: to_class(MCPServerConfigValue, x), self.servers)
return result
-class SessionLogLevel(Enum):
- """Log severity level. Determines how the message is displayed in the timeline. Defaults to
- "info".
- """
- ERROR = "error"
- INFO = "info"
- WARNING = "warning"
-
@dataclass
-class LogRequest:
- message: str
- """Human-readable message"""
-
- ephemeral: bool | None = None
- """When true, the message is transient and not persisted to the session event log on disk"""
+class MCPConfigAddRequest:
+ config: MCPConfigAddRequestMCPServerConfig
+ """MCP server configuration (local/stdio or remote/http)"""
- level: SessionLogLevel | None = None
- """Log severity level. Determines how the message is displayed in the timeline. Defaults to
- "info".
- """
- url: str | None = None
- """Optional URL the user can open in their browser for more details"""
+ name: str
+ """Unique name for the MCP server"""
@staticmethod
- def from_dict(obj: Any) -> 'LogRequest':
+ def from_dict(obj: Any) -> 'MCPConfigAddRequest':
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)
+ config = MCPConfigAddRequestMCPServerConfig.from_dict(obj.get("config"))
+ name = from_str(obj.get("name"))
+ return MCPConfigAddRequest(config, name)
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["config"] = to_class(MCPConfigAddRequestMCPServerConfig, self.config)
+ result["name"] = from_str(self.name)
return result
@dataclass
-class ShellExecResult:
- process_id: str
- """Unique identifier for tracking streamed output"""
+class MCPConfigUpdateRequest:
+ config: MCPConfigUpdateRequestMCPServerConfig
+ """MCP server configuration (local/stdio or remote/http)"""
+
+ name: str
+ """Name of the MCP server to update"""
@staticmethod
- def from_dict(obj: Any) -> 'ShellExecResult':
+ def from_dict(obj: Any) -> 'MCPConfigUpdateRequest':
assert isinstance(obj, dict)
- process_id = from_str(obj.get("processId"))
- return ShellExecResult(process_id)
+ config = MCPConfigUpdateRequestMCPServerConfig.from_dict(obj.get("config"))
+ name = from_str(obj.get("name"))
+ return MCPConfigUpdateRequest(config, name)
def to_dict(self) -> dict:
result: dict = {}
- result["processId"] = from_str(self.process_id)
+ result["config"] = to_class(MCPConfigUpdateRequestMCPServerConfig, self.config)
+ result["name"] = from_str(self.name)
return result
@dataclass
-class ShellExecRequest:
- command: str
- """Shell command to execute"""
-
- cwd: str | None = None
- """Working directory (defaults to session working directory)"""
-
- timeout: int | None = None
- """Timeout in milliseconds (default: 30000)"""
+class MCPDiscoverResult:
+ servers: list[ServerElement]
+ """MCP servers discovered from all sources"""
@staticmethod
- def from_dict(obj: Any) -> 'ShellExecRequest':
+ def from_dict(obj: Any) -> 'MCPDiscoverResult':
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)
+ servers = from_list(ServerElement.from_dict, obj.get("servers"))
+ return MCPDiscoverResult(servers)
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)
+ result["servers"] = from_list(lambda x: to_class(ServerElement, x), self.servers)
return result
@dataclass
-class ShellKillResult:
- killed: bool
- """Whether the signal was sent successfully"""
+class ModelCapabilitiesOverride:
+ """Override individual model capabilities resolved by the runtime"""
+
+ limits: ModelCapabilitiesOverrideLimits | None = None
+ """Token limits for prompts, outputs, and context window"""
+
+ supports: ModelCapabilitiesOverrideSupports | None = None
+ """Feature flags indicating what the model supports"""
@staticmethod
- def from_dict(obj: Any) -> 'ShellKillResult':
+ def from_dict(obj: Any) -> 'ModelCapabilitiesOverride':
assert isinstance(obj, dict)
- killed = from_bool(obj.get("killed"))
- return ShellKillResult(killed)
+ 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["killed"] = from_bool(self.killed)
+ 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
-class ShellKillSignal(Enum):
- """Signal to send (default: SIGTERM)"""
-
- SIGINT = "SIGINT"
- SIGKILL = "SIGKILL"
- SIGTERM = "SIGTERM"
-
@dataclass
-class ShellKillRequest:
- process_id: str
- """Process identifier returned by shell.exec"""
-
- signal: ShellKillSignal | None = None
- """Signal to send (default: SIGTERM)"""
+class MCPServerList:
+ servers: list[MCPServer]
+ """Configured MCP servers"""
@staticmethod
- def from_dict(obj: Any) -> 'ShellKillRequest':
+ def from_dict(obj: Any) -> 'MCPServerList':
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)
+ servers = from_list(MCPServer.from_dict, obj.get("servers"))
+ return MCPServerList(servers)
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["servers"] = from_list(lambda x: to_class(MCPServer, x), self.servers)
return result
@dataclass
-class HistoryCompactContextWindow:
- """Post-compaction context window usage breakdown"""
-
- current_tokens: int
- """Current total tokens in the context window (system + conversation + tool definitions)"""
-
- messages_length: int
- """Current number of messages in the conversation"""
-
- token_limit: int
- """Maximum token count for the model's context window"""
-
- conversation_tokens: int | None = None
- """Token count from non-system messages (user, assistant, tool)"""
-
- system_tokens: int | None = None
- """Token count from system message(s)"""
-
- tool_definitions_tokens: int | None = None
- """Token count from tool definitions"""
+class UIElicitationArrayEnumField:
+ items: UIElicitationArrayEnumFieldItems
+ type: UIElicitationArrayEnumFieldType
+ default: list[str] | None = None
+ description: str | None = None
+ max_items: float | None = None
+ min_items: float | None = None
+ title: str | None = None
@staticmethod
- def from_dict(obj: Any) -> 'HistoryCompactContextWindow':
+ def from_dict(obj: Any) -> 'UIElicitationArrayEnumField':
assert isinstance(obj, dict)
- current_tokens = from_int(obj.get("currentTokens"))
- messages_length = from_int(obj.get("messagesLength"))
- token_limit = from_int(obj.get("tokenLimit"))
- conversation_tokens = from_union([from_int, from_none], obj.get("conversationTokens"))
- system_tokens = from_union([from_int, from_none], obj.get("systemTokens"))
- tool_definitions_tokens = from_union([from_int, from_none], obj.get("toolDefinitionsTokens"))
- return HistoryCompactContextWindow(current_tokens, messages_length, token_limit, conversation_tokens, system_tokens, tool_definitions_tokens)
+ items = UIElicitationArrayEnumFieldItems.from_dict(obj.get("items"))
+ type = UIElicitationArrayEnumFieldType(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"))
+ title = from_union([from_str, from_none], obj.get("title"))
+ return UIElicitationArrayEnumField(items, type, default, description, max_items, min_items, title)
def to_dict(self) -> dict:
result: dict = {}
- result["currentTokens"] = from_int(self.current_tokens)
- result["messagesLength"] = from_int(self.messages_length)
- result["tokenLimit"] = from_int(self.token_limit)
- if self.conversation_tokens is not None:
- result["conversationTokens"] = from_union([from_int, from_none], self.conversation_tokens)
- if self.system_tokens is not None:
- result["systemTokens"] = from_union([from_int, from_none], self.system_tokens)
- if self.tool_definitions_tokens is not None:
- result["toolDefinitionsTokens"] = from_union([from_int, from_none], self.tool_definitions_tokens)
+ result["items"] = to_class(UIElicitationArrayEnumFieldItems, self.items)
+ result["type"] = to_enum(UIElicitationArrayEnumFieldType, self.type)
+ if self.default is not None:
+ result["default"] = from_union([lambda x: from_list(from_str, x), from_none], self.default)
+ 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)
+ if self.min_items is not None:
+ result["minItems"] = from_union([to_float, from_none], self.min_items)
+ 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 HistoryCompactResult:
- 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"""
+class UIElicitationArrayAnyOfField:
+ items: UIElicitationArrayAnyOfFieldItems
+ type: UIElicitationArrayEnumFieldType
+ default: list[str] | None = None
+ description: str | None = None
+ max_items: float | None = None
+ min_items: float | None = None
+ title: str | None = None
@staticmethod
- def from_dict(obj: Any) -> 'HistoryCompactResult':
+ def from_dict(obj: Any) -> 'UIElicitationArrayAnyOfField':
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)
+ items = UIElicitationArrayAnyOfFieldItems.from_dict(obj.get("items"))
+ type = UIElicitationArrayEnumFieldType(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"))
+ title = from_union([from_str, from_none], obj.get("title"))
+ return UIElicitationArrayAnyOfField(items, type, default, description, max_items, min_items, title)
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)
+ result["items"] = to_class(UIElicitationArrayAnyOfFieldItems, self.items)
+ result["type"] = to_enum(UIElicitationArrayEnumFieldType, self.type)
+ if self.default is not None:
+ result["default"] = from_union([lambda x: from_list(from_str, x), from_none], self.default)
+ 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)
+ if self.min_items is not None:
+ result["minItems"] = from_union([to_float, from_none], self.min_items)
+ 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 HistoryTruncateResult:
- events_removed: int
- """Number of events that were removed"""
+class UIHandlePendingElicitationRequest:
+ request_id: str
+ """The unique request ID from the elicitation.requested event"""
+
+ result: UIElicitationResponse
+ """The elicitation response (accept with form values, decline, or cancel)"""
@staticmethod
- def from_dict(obj: Any) -> 'HistoryTruncateResult':
+ def from_dict(obj: Any) -> 'UIHandlePendingElicitationRequest':
assert isinstance(obj, dict)
- events_removed = from_int(obj.get("eventsRemoved"))
- return HistoryTruncateResult(events_removed)
+ request_id = from_str(obj.get("requestId"))
+ result = UIElicitationResponse.from_dict(obj.get("result"))
+ return UIHandlePendingElicitationRequest(request_id, result)
def to_dict(self) -> dict:
result: dict = {}
- result["eventsRemoved"] = from_int(self.events_removed)
+ result["requestId"] = from_str(self.request_id)
+ result["result"] = to_class(UIElicitationResponse, self.result)
return result
-# Experimental: this type is part of an experimental API and may change or be removed.
@dataclass
-class HistoryTruncateRequest:
- event_id: str
- """Event ID to truncate to. This event and all events after it are removed from the session."""
+class PermissionDecisionRequest:
+ request_id: str
+ """Request ID of the pending permission request"""
+
+ result: PermissionDecision
@staticmethod
- def from_dict(obj: Any) -> 'HistoryTruncateRequest':
+ def from_dict(obj: Any) -> 'PermissionDecisionRequest':
assert isinstance(obj, dict)
- event_id = from_str(obj.get("eventId"))
- return HistoryTruncateRequest(event_id)
+ request_id = from_str(obj.get("requestId"))
+ result = PermissionDecision.from_dict(obj.get("result"))
+ return PermissionDecisionRequest(request_id, result)
def to_dict(self) -> dict:
result: dict = {}
- result["eventId"] = from_str(self.event_id)
+ result["requestId"] = from_str(self.request_id)
+ result["result"] = to_class(PermissionDecision, self.result)
return result
@dataclass
-class UsageMetricsCodeChanges:
- """Aggregated code change metrics"""
-
- files_modified_count: int
- """Number of distinct files modified"""
+class ModelCapabilitiesClass:
+ """Override individual model capabilities resolved by the runtime"""
- lines_added: int
- """Total lines of code added"""
+ limits: ModelCapabilitiesLimitsClass | None = None
+ """Token limits for prompts, outputs, and context window"""
- lines_removed: int
- """Total lines of code removed"""
+ supports: ModelCapabilitiesOverrideSupports | None = None
+ """Feature flags indicating what the model supports"""
@staticmethod
- def from_dict(obj: Any) -> 'UsageMetricsCodeChanges':
+ def from_dict(obj: Any) -> 'ModelCapabilitiesClass':
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)
+ limits = from_union([ModelCapabilitiesLimitsClass.from_dict, from_none], obj.get("limits"))
+ supports = from_union([ModelCapabilitiesOverrideSupports.from_dict, from_none], obj.get("supports"))
+ return ModelCapabilitiesClass(limits, supports)
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)
+ if self.limits is not None:
+ result["limits"] = from_union([lambda x: to_class(ModelCapabilitiesLimitsClass, 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 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"""
+class WorkspacesGetWorkspaceResult:
+ workspace: Workspace | None = None
+ """Current workspace metadata, or null if not available"""
@staticmethod
- def from_dict(obj: Any) -> 'UsageMetricsModelMetricRequests':
+ def from_dict(obj: Any) -> 'WorkspacesGetWorkspaceResult':
assert isinstance(obj, dict)
- cost = from_float(obj.get("cost"))
- count = from_int(obj.get("count"))
- return UsageMetricsModelMetricRequests(cost, count)
+ workspace = from_union([Workspace.from_dict, from_none], obj.get("workspace"))
+ return WorkspacesGetWorkspaceResult(workspace)
def to_dict(self) -> dict:
result: dict = {}
- result["cost"] = to_float(self.cost)
- result["count"] = from_int(self.count)
+ result["workspace"] = from_union([lambda x: to_class(Workspace, x), from_none], self.workspace)
return result
@dataclass
-class UsageMetricsModelMetricUsage:
- """Token usage metrics for this model"""
-
- cache_read_tokens: int
- """Total tokens read from prompt cache"""
+class InstructionsGetSourcesResult:
+ sources: list[InstructionsSources]
+ """Instruction sources for the session"""
- cache_write_tokens: int
- """Total tokens written to prompt cache"""
-
- input_tokens: int
- """Total input tokens consumed"""
+ @staticmethod
+ def from_dict(obj: Any) -> 'InstructionsGetSourcesResult':
+ assert isinstance(obj, dict)
+ sources = from_list(InstructionsSources.from_dict, obj.get("sources"))
+ return InstructionsGetSourcesResult(sources)
- output_tokens: int
- """Total output tokens produced"""
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["sources"] = from_list(lambda x: to_class(InstructionsSources, x), self.sources)
+ return result
- reasoning_tokens: int | None = None
- """Total output tokens used for reasoning"""
+# Experimental: this type is part of an experimental API and may change or be removed.
+@dataclass
+class ExtensionList:
+ extensions: list[Extension]
+ """Discovered extensions and their current status"""
@staticmethod
- def from_dict(obj: Any) -> 'UsageMetricsModelMetricUsage':
+ def from_dict(obj: Any) -> 'ExtensionList':
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)
+ extensions = from_list(Extension.from_dict, obj.get("extensions"))
+ return ExtensionList(extensions)
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["extensions"] = from_list(lambda x: to_class(Extension, x), self.extensions)
return result
@dataclass
-class UsageMetricsModelMetric:
- requests: UsageMetricsModelMetricRequests
- """Request count and cost metrics for this model"""
-
- usage: UsageMetricsModelMetricUsage
- """Token usage metrics for this model"""
+class UIElicitationSchemaProperty:
+ type: UIElicitationSchemaPropertyNumberType
+ default: float | bool | list[str] | str | None = None
+ description: str | None = None
+ enum: list[str] | None = None
+ enum_names: list[str] | None = None
+ title: str | None = None
+ one_of: list[UIElicitationSchemaPropertyOneOf] | None = None
+ items: UIElicitationArrayFieldItems | None = None
+ max_items: float | None = None
+ min_items: float | None = None
+ format: UIElicitationSchemaPropertyStringFormat | None = None
+ max_length: float | None = None
+ min_length: float | None = None
+ maximum: float | None = None
+ minimum: float | None = None
@staticmethod
- def from_dict(obj: Any) -> 'UsageMetricsModelMetric':
+ def from_dict(obj: Any) -> 'UIElicitationSchemaProperty':
assert isinstance(obj, dict)
- requests = UsageMetricsModelMetricRequests.from_dict(obj.get("requests"))
- usage = UsageMetricsModelMetricUsage.from_dict(obj.get("usage"))
- return UsageMetricsModelMetric(requests, usage)
+ type = UIElicitationSchemaPropertyNumberType(obj.get("type"))
+ default = from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], obj.get("default"))
+ description = from_union([from_str, from_none], obj.get("description"))
+ enum = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enum"))
+ enum_names = from_union([lambda x: from_list(from_str, x), from_none], obj.get("enumNames"))
+ title = from_union([from_str, from_none], obj.get("title"))
+ one_of = from_union([lambda x: from_list(UIElicitationSchemaPropertyOneOf.from_dict, x), from_none], obj.get("oneOf"))
+ items = from_union([UIElicitationArrayFieldItems.from_dict, from_none], obj.get("items"))
+ max_items = from_union([from_float, from_none], obj.get("maxItems"))
+ min_items = from_union([from_float, from_none], obj.get("minItems"))
+ format = from_union([UIElicitationSchemaPropertyStringFormat, from_none], obj.get("format"))
+ max_length = from_union([from_float, from_none], obj.get("maxLength"))
+ min_length = from_union([from_float, from_none], obj.get("minLength"))
+ maximum = from_union([from_float, from_none], obj.get("maximum"))
+ minimum = from_union([from_float, from_none], obj.get("minimum"))
+ return UIElicitationSchemaProperty(type, default, description, enum, enum_names, title, one_of, items, max_items, min_items, format, max_length, min_length, maximum, minimum)
def to_dict(self) -> dict:
result: dict = {}
- result["requests"] = to_class(UsageMetricsModelMetricRequests, self.requests)
- result["usage"] = to_class(UsageMetricsModelMetricUsage, self.usage)
+ result["type"] = to_enum(UIElicitationSchemaPropertyNumberType, self.type)
+ if self.default is not None:
+ result["default"] = from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str, from_none], self.default)
+ if self.description is not None:
+ result["description"] = from_union([from_str, from_none], self.description)
+ if self.enum is not None:
+ result["enum"] = from_union([lambda x: from_list(from_str, x), from_none], self.enum)
+ 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)
+ if self.one_of is not None:
+ result["oneOf"] = from_union([lambda x: from_list(lambda x: to_class(UIElicitationSchemaPropertyOneOf, x), x), from_none], self.one_of)
+ 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)
+ if self.min_items is not None:
+ result["minItems"] = from_union([to_float, from_none], self.min_items)
+ if self.format is not None:
+ result["format"] = from_union([lambda x: to_enum(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.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)
return result
# Experimental: this type is part of an experimental API and may change or be removed.
@@ -2944,418 +3802,408 @@ class UsageGetMetricsResult:
@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_int(obj.get("sessionStartTime"))
- total_api_duration_ms = from_float(obj.get("totalApiDurationMs"))
- total_premium_request_cost = from_float(obj.get("totalPremiumRequestCost"))
- total_user_requests = from_int(obj.get("totalUserRequests"))
- current_model = from_union([from_str, from_none], obj.get("currentModel"))
- return 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)
+ code_changes = UsageMetricsCodeChanges.from_dict(obj.get("codeChanges"))
+ last_call_input_tokens = from_int(obj.get("lastCallInputTokens"))
+ last_call_output_tokens = from_int(obj.get("lastCallOutputTokens"))
+ model_metrics = from_dict(UsageMetricsModelMetric.from_dict, obj.get("modelMetrics"))
+ session_start_time = from_int(obj.get("sessionStartTime"))
+ total_api_duration_ms = from_float(obj.get("totalApiDurationMs"))
+ total_premium_request_cost = from_float(obj.get("totalPremiumRequestCost"))
+ total_user_requests = from_int(obj.get("totalUserRequests"))
+ current_model = from_union([from_str, from_none], obj.get("currentModel"))
+ return UsageGetMetricsResult(code_changes, last_call_input_tokens, last_call_output_tokens, model_metrics, session_start_time, total_api_duration_ms, total_premium_request_cost, total_user_requests, current_model)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["codeChanges"] = to_class(UsageMetricsCodeChanges, self.code_changes)
+ result["lastCallInputTokens"] = from_int(self.last_call_input_tokens)
+ result["lastCallOutputTokens"] = from_int(self.last_call_output_tokens)
+ result["modelMetrics"] = from_dict(lambda x: to_class(UsageMetricsModelMetric, x), self.model_metrics)
+ result["sessionStartTime"] = from_int(self.session_start_time)
+ result["totalApiDurationMs"] = to_float(self.total_api_duration_ms)
+ result["totalPremiumRequestCost"] = to_float(self.total_premium_request_cost)
+ result["totalUserRequests"] = from_int(self.total_user_requests)
+ if self.current_model is not None:
+ result["currentModel"] = from_union([from_str, from_none], self.current_model)
+ return result
+
+@dataclass
+class SessionFSReaddirWithTypesResult:
+ entries: list[SessionFSReaddirWithTypesEntry]
+ """Directory entries with type information"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesResult':
+ assert isinstance(obj, dict)
+ entries = from_list(SessionFSReaddirWithTypesEntry.from_dict, obj.get("entries"))
+ return SessionFSReaddirWithTypesResult(entries)
+
+ def to_dict(self) -> dict:
+ result: dict = {}
+ result["entries"] = from_list(lambda x: to_class(SessionFSReaddirWithTypesEntry, x), self.entries)
+ return result
+
+@dataclass
+class UIElicitationSchema:
+ """JSON Schema describing the form fields to present to the user"""
+
+ properties: dict[str, UIElicitationSchemaProperty]
+ """Form field definitions, keyed by field name"""
+
+ type: RequestedSchemaType
+ """Schema type indicator (always 'object')"""
+
+ required: list[str] | None = None
+ """List of required field names"""
+
+ @staticmethod
+ def from_dict(obj: Any) -> 'UIElicitationSchema':
+ assert isinstance(obj, dict)
+ properties = from_dict(UIElicitationSchemaProperty.from_dict, obj.get("properties"))
+ type = RequestedSchemaType(obj.get("type"))
+ required = from_union([lambda x: from_list(from_str, x), from_none], obj.get("required"))
+ return UIElicitationSchema(properties, type, required)
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)
+ result["properties"] = from_dict(lambda x: to_class(UIElicitationSchemaProperty, x), self.properties)
+ result["type"] = to_enum(RequestedSchemaType, self.type)
+ if self.required is not None:
+ result["required"] = from_union([lambda x: from_list(from_str, x), from_none], self.required)
return result
@dataclass
-class SessionFSReadFileResult:
- content: str
- """File content as UTF-8 string"""
+class UIElicitationRequest:
+ message: str
+ """Message describing what information is needed from the user"""
+
+ requested_schema: UIElicitationSchema
+ """JSON Schema describing the form fields to present to the user"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSReadFileResult':
+ def from_dict(obj: Any) -> 'UIElicitationRequest':
assert isinstance(obj, dict)
- content = from_str(obj.get("content"))
- return SessionFSReadFileResult(content)
+ message = from_str(obj.get("message"))
+ requested_schema = UIElicitationSchema.from_dict(obj.get("requestedSchema"))
+ return UIElicitationRequest(message, requested_schema)
def to_dict(self) -> dict:
result: dict = {}
- result["content"] = from_str(self.content)
+ result["message"] = from_str(self.message)
+ result["requestedSchema"] = to_class(UIElicitationSchema, self.requested_schema)
return result
@dataclass
-class SessionFSReadFileRequest:
- path: str
- """Path using SessionFs conventions"""
+class ModelCapabilities:
+ """Model capabilities and limits"""
- session_id: str
- """Target session identifier"""
+ limits: ModelCapabilitiesLimits | None = None
+ """Token limits for prompts, outputs, and context window"""
+
+ supports: ModelCapabilitiesSupports | None = None
+ """Feature flags indicating what the model supports"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSReadFileRequest':
+ def from_dict(obj: Any) -> 'ModelCapabilities':
assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- return SessionFSReadFileRequest(path, session_id)
+ limits = from_union([ModelCapabilitiesLimits.from_dict, from_none], obj.get("limits"))
+ supports = from_union([ModelCapabilitiesSupports.from_dict, from_none], obj.get("supports"))
+ return ModelCapabilities(limits, supports)
def to_dict(self) -> dict:
result: dict = {}
- result["path"] = from_str(self.path)
- result["sessionId"] = from_str(self.session_id)
+ if self.limits is not None:
+ result["limits"] = from_union([lambda x: to_class(ModelCapabilitiesLimits, x), from_none], self.limits)
+ if self.supports is not None:
+ result["supports"] = from_union([lambda x: to_class(ModelCapabilitiesSupports, x), from_none], self.supports)
return result
@dataclass
-class SessionFSWriteFileRequest:
- content: str
- """Content to write"""
-
- path: str
- """Path using SessionFs conventions"""
+class CapabilitiesClass:
+ """Model capabilities and limits"""
- session_id: str
- """Target session identifier"""
+ limits: CapabilitiesLimits | None = None
+ """Token limits for prompts, outputs, and context window"""
- mode: int | None = None
- """Optional POSIX-style mode for newly created files"""
+ supports: CapabilitiesSupports | None = None
+ """Feature flags indicating what the model supports"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSWriteFileRequest':
+ def from_dict(obj: Any) -> 'CapabilitiesClass':
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)
+ limits = from_union([CapabilitiesLimits.from_dict, from_none], obj.get("limits"))
+ supports = from_union([CapabilitiesSupports.from_dict, from_none], obj.get("supports"))
+ return CapabilitiesClass(limits, supports)
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)
+ if self.limits is not None:
+ result["limits"] = from_union([lambda x: to_class(CapabilitiesLimits, x), from_none], self.limits)
+ if self.supports is not None:
+ result["supports"] = from_union([lambda x: to_class(CapabilitiesSupports, x), from_none], self.supports)
return result
@dataclass
-class SessionFSAppendFileRequest:
- content: str
- """Content to append"""
+class Model:
+ capabilities: CapabilitiesClass
+ """Model capabilities and limits"""
- path: str
- """Path using SessionFs conventions"""
+ id: str
+ """Model identifier (e.g., "claude-sonnet-4.5")"""
- session_id: str
- """Target session identifier"""
+ name: str
+ """Display name"""
- mode: int | None = None
- """Optional POSIX-style mode for newly created files"""
+ billing: ModelBilling | None = None
+ """Billing information"""
+
+ default_reasoning_effort: str | None = None
+ """Default reasoning effort level (only present if model supports reasoning effort)"""
+
+ policy: ModelPolicy | None = None
+ """Policy state (if applicable)"""
+
+ supported_reasoning_efforts: list[str] | None = None
+ """Supported reasoning effort levels (only present if model supports reasoning effort)"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSAppendFileRequest':
+ def from_dict(obj: Any) -> 'Model':
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)
+ capabilities = CapabilitiesClass.from_dict(obj.get("capabilities"))
+ id = from_str(obj.get("id"))
+ name = from_str(obj.get("name"))
+ billing = from_union([ModelBilling.from_dict, from_none], obj.get("billing"))
+ default_reasoning_effort = from_union([from_str, from_none], obj.get("defaultReasoningEffort"))
+ policy = from_union([ModelPolicy.from_dict, from_none], obj.get("policy"))
+ supported_reasoning_efforts = from_union([lambda x: from_list(from_str, x), from_none], obj.get("supportedReasoningEfforts"))
+ return Model(capabilities, id, name, billing, default_reasoning_effort, policy, supported_reasoning_efforts)
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["capabilities"] = to_class(CapabilitiesClass, self.capabilities)
+ result["id"] = from_str(self.id)
+ result["name"] = from_str(self.name)
+ if self.billing is not None:
+ result["billing"] = from_union([lambda x: to_class(ModelBilling, x), from_none], self.billing)
+ if self.default_reasoning_effort is not None:
+ result["defaultReasoningEffort"] = from_union([from_str, from_none], self.default_reasoning_effort)
+ if self.policy is not None:
+ result["policy"] = from_union([lambda x: to_class(ModelPolicy, x), from_none], self.policy)
+ if self.supported_reasoning_efforts is not None:
+ result["supportedReasoningEfforts"] = from_union([lambda x: from_list(from_str, x), from_none], self.supported_reasoning_efforts)
return result
@dataclass
-class SessionFSExistsResult:
- exists: bool
- """Whether the path exists"""
+class ModelList:
+ models: list[Model]
+ """List of available models with full metadata"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSExistsResult':
+ def from_dict(obj: Any) -> 'ModelList':
assert isinstance(obj, dict)
- exists = from_bool(obj.get("exists"))
- return SessionFSExistsResult(exists)
+ models = from_list(Model.from_dict, obj.get("models"))
+ return ModelList(models)
def to_dict(self) -> dict:
result: dict = {}
- result["exists"] = from_bool(self.exists)
+ result["models"] = from_list(lambda x: to_class(Model, x), self.models)
return result
@dataclass
-class SessionFSExistsRequest:
- path: str
- """Path using SessionFs conventions"""
+class ModelSwitchToRequest:
+ model_id: str
+ """Model identifier to switch to"""
- session_id: str
- """Target session identifier"""
+ model_capabilities: ModelCapabilitiesClass | None = None
+ """Override individual model capabilities resolved by the runtime"""
+
+ reasoning_effort: str | None = None
+ """Reasoning effort level to use for the model"""
@staticmethod
- def from_dict(obj: Any) -> 'SessionFSExistsRequest':
+ def from_dict(obj: Any) -> 'ModelSwitchToRequest':
assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- return SessionFSExistsRequest(path, session_id)
+ model_id = from_str(obj.get("modelId"))
+ model_capabilities = from_union([ModelCapabilitiesClass.from_dict, from_none], obj.get("modelCapabilities"))
+ reasoning_effort = from_union([from_str, from_none], obj.get("reasoningEffort"))
+ return ModelSwitchToRequest(model_id, model_capabilities, reasoning_effort)
def to_dict(self) -> dict:
result: dict = {}
- result["path"] = from_str(self.path)
- result["sessionId"] = from_str(self.session_id)
+ result["modelId"] = from_str(self.model_id)
+ if self.model_capabilities is not None:
+ result["modelCapabilities"] = from_union([lambda x: to_class(ModelCapabilitiesClass, x), from_none], self.model_capabilities)
+ if self.reasoning_effort is not None:
+ result["reasoningEffort"] = from_union([from_str, from_none], self.reasoning_effort)
return result
-@dataclass
-class SessionFSStatResult:
- birthtime: datetime
- """ISO 8601 timestamp of creation"""
+def model_capabilities_from_dict(s: Any) -> ModelCapabilities:
+ return ModelCapabilities.from_dict(s)
- is_directory: bool
- """Whether the path is a directory"""
+def model_capabilities_to_dict(x: ModelCapabilities) -> Any:
+ return to_class(ModelCapabilities, x)
- is_file: bool
- """Whether the path is a file"""
+def model_capabilities_limits_vision_from_dict(s: Any) -> ModelCapabilitiesLimitsVision:
+ return ModelCapabilitiesLimitsVision.from_dict(s)
- mtime: datetime
- """ISO 8601 timestamp of last modification"""
+def model_capabilities_limits_vision_to_dict(x: ModelCapabilitiesLimitsVision) -> Any:
+ return to_class(ModelCapabilitiesLimitsVision, x)
- size: int
- """File size in bytes"""
+def mcp_server_config_from_dict(s: Any) -> MCPServerConfig:
+ return MCPServerConfig.from_dict(s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSStatResult':
- assert isinstance(obj, dict)
- birthtime = from_datetime(obj.get("birthtime"))
- is_directory = from_bool(obj.get("isDirectory"))
- is_file = from_bool(obj.get("isFile"))
- mtime = from_datetime(obj.get("mtime"))
- size = from_int(obj.get("size"))
- return SessionFSStatResult(birthtime, is_directory, is_file, mtime, size)
+def mcp_server_config_to_dict(x: MCPServerConfig) -> Any:
+ return to_class(MCPServerConfig, x)
- def to_dict(self) -> dict:
- result: dict = {}
- result["birthtime"] = self.birthtime.isoformat()
- result["isDirectory"] = from_bool(self.is_directory)
- result["isFile"] = from_bool(self.is_file)
- result["mtime"] = self.mtime.isoformat()
- result["size"] = from_int(self.size)
- return result
+def filter_mapping_from_dict(s: Any) -> dict[str, FilterMappingString] | FilterMappingString:
+ return from_union([lambda x: from_dict(FilterMappingString, x), FilterMappingString], s)
-@dataclass
-class SessionFSStatRequest:
- path: str
- """Path using SessionFs conventions"""
+def filter_mapping_to_dict(x: dict[str, FilterMappingString] | FilterMappingString) -> Any:
+ return from_union([lambda x: from_dict(lambda x: to_enum(FilterMappingString, x), x), lambda x: to_enum(FilterMappingString, x)], x)
- session_id: str
- """Target session identifier"""
+def discovered_mcp_server_from_dict(s: Any) -> DiscoveredMCPServer:
+ return DiscoveredMCPServer.from_dict(s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSStatRequest':
- assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- return SessionFSStatRequest(path, session_id)
+def discovered_mcp_server_to_dict(x: DiscoveredMCPServer) -> Any:
+ return to_class(DiscoveredMCPServer, x)
- def to_dict(self) -> dict:
- result: dict = {}
- result["path"] = from_str(self.path)
- result["sessionId"] = from_str(self.session_id)
- return result
+def server_skill_list_from_dict(s: Any) -> ServerSkillList:
+ return ServerSkillList.from_dict(s)
+
+def server_skill_list_to_dict(x: ServerSkillList) -> Any:
+ return to_class(ServerSkillList, x)
+
+def server_skill_from_dict(s: Any) -> ServerSkill:
+ return ServerSkill.from_dict(s)
+
+def server_skill_to_dict(x: ServerSkill) -> Any:
+ return to_class(ServerSkill, x)
+
+def current_model_from_dict(s: Any) -> CurrentModel:
+ return CurrentModel.from_dict(s)
+
+def current_model_to_dict(x: CurrentModel) -> Any:
+ return to_class(CurrentModel, x)
+
+def model_capabilities_override_from_dict(s: Any) -> ModelCapabilitiesOverride:
+ return ModelCapabilitiesOverride.from_dict(s)
+
+def model_capabilities_override_to_dict(x: ModelCapabilitiesOverride) -> Any:
+ return to_class(ModelCapabilitiesOverride, x)
+
+def session_mode_from_dict(s: Any) -> SessionMode:
+ return SessionMode(s)
-@dataclass
-class SessionFSMkdirRequest:
- path: str
- """Path using SessionFs conventions"""
+def session_mode_to_dict(x: SessionMode) -> Any:
+ return to_enum(SessionMode, x)
- session_id: str
- """Target session identifier"""
+def agent_info_from_dict(s: Any) -> AgentInfo:
+ return AgentInfo.from_dict(s)
- mode: int | None = None
- """Optional POSIX-style mode for newly created directories"""
+def agent_info_to_dict(x: AgentInfo) -> Any:
+ return to_class(AgentInfo, x)
- recursive: bool | None = None
- """Create parent directories as needed"""
+def mcp_server_list_from_dict(s: Any) -> MCPServerList:
+ return MCPServerList.from_dict(s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSMkdirRequest':
- assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- mode = from_union([from_int, from_none], obj.get("mode"))
- recursive = from_union([from_bool, from_none], obj.get("recursive"))
- return SessionFSMkdirRequest(path, session_id, mode, recursive)
+def mcp_server_list_to_dict(x: MCPServerList) -> Any:
+ return to_class(MCPServerList, x)
- 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)
- return result
+def tool_call_result_from_dict(s: Any) -> ToolCallResult:
+ return ToolCallResult.from_dict(s)
-@dataclass
-class SessionFSReaddirResult:
- entries: list[str]
- """Entry names in the directory"""
+def tool_call_result_to_dict(x: ToolCallResult) -> Any:
+ return to_class(ToolCallResult, x)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSReaddirResult':
- assert isinstance(obj, dict)
- entries = from_list(from_str, obj.get("entries"))
- return SessionFSReaddirResult(entries)
+def handle_tool_call_result_from_dict(s: Any) -> HandleToolCallResult:
+ return HandleToolCallResult.from_dict(s)
- def to_dict(self) -> dict:
- result: dict = {}
- result["entries"] = from_list(from_str, self.entries)
- return result
+def handle_tool_call_result_to_dict(x: HandleToolCallResult) -> Any:
+ return to_class(HandleToolCallResult, x)
-@dataclass
-class SessionFSReaddirRequest:
- path: str
- """Path using SessionFs conventions"""
+def ui_elicitation_string_enum_field_from_dict(s: Any) -> UIElicitationStringEnumField:
+ return UIElicitationStringEnumField.from_dict(s)
- session_id: str
- """Target session identifier"""
+def ui_elicitation_string_enum_field_to_dict(x: UIElicitationStringEnumField) -> Any:
+ return to_class(UIElicitationStringEnumField, x)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSReaddirRequest':
- assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- return SessionFSReaddirRequest(path, session_id)
+def ui_elicitation_string_one_of_field_from_dict(s: Any) -> UIElicitationStringOneOfField:
+ return UIElicitationStringOneOfField.from_dict(s)
- def to_dict(self) -> dict:
- result: dict = {}
- result["path"] = from_str(self.path)
- result["sessionId"] = from_str(self.session_id)
- return result
+def ui_elicitation_string_one_of_field_to_dict(x: UIElicitationStringOneOfField) -> Any:
+ return to_class(UIElicitationStringOneOfField, x)
-class SessionFSReaddirWithTypesEntryType(Enum):
- """Entry type"""
+def ui_elicitation_array_enum_field_from_dict(s: Any) -> UIElicitationArrayEnumField:
+ return UIElicitationArrayEnumField.from_dict(s)
- DIRECTORY = "directory"
- FILE = "file"
+def ui_elicitation_array_enum_field_to_dict(x: UIElicitationArrayEnumField) -> Any:
+ return to_class(UIElicitationArrayEnumField, x)
-@dataclass
-class SessionFSReaddirWithTypesEntry:
- name: str
- """Entry name"""
+def ui_elicitation_array_any_of_field_from_dict(s: Any) -> UIElicitationArrayAnyOfField:
+ return UIElicitationArrayAnyOfField.from_dict(s)
- type: SessionFSReaddirWithTypesEntryType
- """Entry type"""
+def ui_elicitation_array_any_of_field_to_dict(x: UIElicitationArrayAnyOfField) -> Any:
+ return to_class(UIElicitationArrayAnyOfField, x)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesEntry':
- assert isinstance(obj, dict)
- name = from_str(obj.get("name"))
- type = SessionFSReaddirWithTypesEntryType(obj.get("type"))
- return SessionFSReaddirWithTypesEntry(name, type)
+def ui_elicitation_response_from_dict(s: Any) -> UIElicitationResponse:
+ return UIElicitationResponse.from_dict(s)
- def to_dict(self) -> dict:
- result: dict = {}
- result["name"] = from_str(self.name)
- result["type"] = to_enum(SessionFSReaddirWithTypesEntryType, self.type)
- return result
+def ui_elicitation_response_to_dict(x: UIElicitationResponse) -> Any:
+ return to_class(UIElicitationResponse, x)
-@dataclass
-class SessionFSReaddirWithTypesResult:
- entries: list[SessionFSReaddirWithTypesEntry]
- """Directory entries with type information"""
+def ui_elicitation_response_action_from_dict(s: Any) -> UIElicitationResponseAction:
+ return UIElicitationResponseAction(s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesResult':
- assert isinstance(obj, dict)
- entries = from_list(SessionFSReaddirWithTypesEntry.from_dict, obj.get("entries"))
- return SessionFSReaddirWithTypesResult(entries)
+def ui_elicitation_response_action_to_dict(x: UIElicitationResponseAction) -> Any:
+ return to_enum(UIElicitationResponseAction, x)
- def to_dict(self) -> dict:
- result: dict = {}
- result["entries"] = from_list(lambda x: to_class(SessionFSReaddirWithTypesEntry, x), self.entries)
- return result
+def ui_elicitation_response_content_from_dict(s: Any) -> dict[str, float | bool | list[str] | str]:
+ return from_dict(lambda x: from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], x), s)
-@dataclass
-class SessionFSReaddirWithTypesRequest:
- path: str
- """Path using SessionFs conventions"""
+def ui_elicitation_response_content_to_dict(x: dict[str, float | bool | list[str] | str]) -> Any:
+ return from_dict(lambda x: from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x), x)
- session_id: str
- """Target session identifier"""
+def ui_elicitation_field_value_from_dict(s: Any) -> float | bool | list[str] | str:
+ return from_union([from_float, from_bool, lambda x: from_list(from_str, x), from_str], s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSReaddirWithTypesRequest':
- assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- return SessionFSReaddirWithTypesRequest(path, session_id)
+def ui_elicitation_field_value_to_dict(x: float | bool | list[str] | str) -> Any:
+ return from_union([to_float, from_bool, lambda x: from_list(from_str, x), from_str], x)
- def to_dict(self) -> dict:
- result: dict = {}
- result["path"] = from_str(self.path)
- result["sessionId"] = from_str(self.session_id)
- return result
+def ui_handle_pending_elicitation_request_from_dict(s: Any) -> UIHandlePendingElicitationRequest:
+ return UIHandlePendingElicitationRequest.from_dict(s)
-@dataclass
-class SessionFSRmRequest:
- path: str
- """Path using SessionFs conventions"""
+def ui_handle_pending_elicitation_request_to_dict(x: UIHandlePendingElicitationRequest) -> Any:
+ return to_class(UIHandlePendingElicitationRequest, x)
- session_id: str
- """Target session identifier"""
+def ui_elicitation_result_from_dict(s: Any) -> UIElicitationResult:
+ return UIElicitationResult.from_dict(s)
- force: bool | None = None
- """Ignore errors if the path does not exist"""
+def ui_elicitation_result_to_dict(x: UIElicitationResult) -> Any:
+ return to_class(UIElicitationResult, x)
- recursive: bool | None = None
- """Remove directories and their contents recursively"""
+def permission_decision_request_from_dict(s: Any) -> PermissionDecisionRequest:
+ return PermissionDecisionRequest.from_dict(s)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSRmRequest':
- assert isinstance(obj, dict)
- path = from_str(obj.get("path"))
- session_id = from_str(obj.get("sessionId"))
- force = from_union([from_bool, from_none], obj.get("force"))
- recursive = from_union([from_bool, from_none], obj.get("recursive"))
- return SessionFSRmRequest(path, session_id, force, recursive)
+def permission_decision_request_to_dict(x: PermissionDecisionRequest) -> Any:
+ return to_class(PermissionDecisionRequest, x)
- 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)
- return result
+def permission_decision_from_dict(s: Any) -> PermissionDecision:
+ return PermissionDecision.from_dict(s)
-@dataclass
-class SessionFSRenameRequest:
- dest: str
- """Destination path using SessionFs conventions"""
+def permission_decision_to_dict(x: PermissionDecision) -> Any:
+ return to_class(PermissionDecision, x)
- session_id: str
- """Target session identifier"""
+def permission_request_result_from_dict(s: Any) -> PermissionRequestResult:
+ return PermissionRequestResult.from_dict(s)
- src: str
- """Source path using SessionFs conventions"""
+def permission_request_result_to_dict(x: PermissionRequestResult) -> Any:
+ return to_class(PermissionRequestResult, x)
- @staticmethod
- def from_dict(obj: Any) -> 'SessionFSRenameRequest':
- assert isinstance(obj, dict)
- dest = from_str(obj.get("dest"))
- session_id = from_str(obj.get("sessionId"))
- src = from_str(obj.get("src"))
- return SessionFSRenameRequest(dest, session_id, src)
+def session_log_level_from_dict(s: Any) -> SessionLogLevel:
+ return SessionLogLevel(s)
- 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)
- return result
+def session_log_level_to_dict(x: SessionLogLevel) -> Any:
+ return to_enum(SessionLogLevel, x)
def ping_result_from_dict(s: Any) -> PingResult:
return PingResult.from_dict(s)
@@ -3435,12 +4283,6 @@ def skills_config_set_disabled_skills_request_from_dict(s: Any) -> SkillsConfigS
def skills_config_set_disabled_skills_request_to_dict(x: SkillsConfigSetDisabledSkillsRequest) -> Any:
return to_class(SkillsConfigSetDisabledSkillsRequest, x)
-def server_skill_list_from_dict(s: Any) -> ServerSkillList:
- return ServerSkillList.from_dict(s)
-
-def server_skill_list_to_dict(x: ServerSkillList) -> Any:
- return to_class(ServerSkillList, x)
-
def skills_discover_request_from_dict(s: Any) -> SkillsDiscoverRequest:
return SkillsDiscoverRequest.from_dict(s)
@@ -3471,12 +4313,6 @@ def sessions_fork_request_from_dict(s: Any) -> SessionsForkRequest:
def sessions_fork_request_to_dict(x: SessionsForkRequest) -> Any:
return to_class(SessionsForkRequest, x)
-def current_model_from_dict(s: Any) -> CurrentModel:
- return CurrentModel.from_dict(s)
-
-def current_model_to_dict(x: CurrentModel) -> Any:
- return to_class(CurrentModel, x)
-
def model_switch_to_result_from_dict(s: Any) -> ModelSwitchToResult:
return ModelSwitchToResult.from_dict(s)
@@ -3489,12 +4325,6 @@ def model_switch_to_request_from_dict(s: Any) -> ModelSwitchToRequest:
def model_switch_to_request_to_dict(x: ModelSwitchToRequest) -> Any:
return to_class(ModelSwitchToRequest, x)
-def session_mode_from_dict(s: Any) -> SessionMode:
- return SessionMode(s)
-
-def session_mode_to_dict(x: SessionMode) -> Any:
- return to_enum(SessionMode, x)
-
def mode_set_request_from_dict(s: Any) -> ModeSetRequest:
return ModeSetRequest.from_dict(s)
@@ -3555,6 +4385,12 @@ def workspaces_create_file_request_from_dict(s: Any) -> WorkspacesCreateFileRequ
def workspaces_create_file_request_to_dict(x: WorkspacesCreateFileRequest) -> Any:
return to_class(WorkspacesCreateFileRequest, x)
+def instructions_get_sources_result_from_dict(s: Any) -> InstructionsGetSourcesResult:
+ return InstructionsGetSourcesResult.from_dict(s)
+
+def instructions_get_sources_result_to_dict(x: InstructionsGetSourcesResult) -> Any:
+ return to_class(InstructionsGetSourcesResult, x)
+
def fleet_start_result_from_dict(s: Any) -> FleetStartResult:
return FleetStartResult.from_dict(s)
@@ -3615,12 +4451,6 @@ def skills_disable_request_from_dict(s: Any) -> SkillsDisableRequest:
def skills_disable_request_to_dict(x: SkillsDisableRequest) -> Any:
return to_class(SkillsDisableRequest, x)
-def mcp_server_list_from_dict(s: Any) -> MCPServerList:
- return MCPServerList.from_dict(s)
-
-def mcp_server_list_to_dict(x: MCPServerList) -> Any:
- return to_class(MCPServerList, x)
-
def mcp_enable_request_from_dict(s: Any) -> MCPEnableRequest:
return MCPEnableRequest.from_dict(s)
@@ -3657,12 +4487,6 @@ def extensions_disable_request_from_dict(s: Any) -> ExtensionsDisableRequest:
def extensions_disable_request_to_dict(x: ExtensionsDisableRequest) -> Any:
return to_class(ExtensionsDisableRequest, x)
-def handle_tool_call_result_from_dict(s: Any) -> HandleToolCallResult:
- return HandleToolCallResult.from_dict(s)
-
-def handle_tool_call_result_to_dict(x: HandleToolCallResult) -> Any:
- return to_class(HandleToolCallResult, x)
-
def tools_handle_pending_tool_call_request_from_dict(s: Any) -> ToolsHandlePendingToolCallRequest:
return ToolsHandlePendingToolCallRequest.from_dict(s)
@@ -3681,42 +4505,12 @@ def commands_handle_pending_command_request_from_dict(s: Any) -> CommandsHandleP
def commands_handle_pending_command_request_to_dict(x: CommandsHandlePendingCommandRequest) -> Any:
return to_class(CommandsHandlePendingCommandRequest, x)
-def ui_elicitation_response_from_dict(s: Any) -> UIElicitationResponse:
- return UIElicitationResponse.from_dict(s)
-
-def ui_elicitation_response_to_dict(x: UIElicitationResponse) -> Any:
- return to_class(UIElicitationResponse, x)
-
def ui_elicitation_request_from_dict(s: Any) -> UIElicitationRequest:
return UIElicitationRequest.from_dict(s)
def ui_elicitation_request_to_dict(x: UIElicitationRequest) -> Any:
return to_class(UIElicitationRequest, x)
-def ui_elicitation_result_from_dict(s: Any) -> UIElicitationResult:
- return UIElicitationResult.from_dict(s)
-
-def ui_elicitation_result_to_dict(x: UIElicitationResult) -> Any:
- return to_class(UIElicitationResult, x)
-
-def ui_handle_pending_elicitation_request_from_dict(s: Any) -> UIHandlePendingElicitationRequest:
- return UIHandlePendingElicitationRequest.from_dict(s)
-
-def ui_handle_pending_elicitation_request_to_dict(x: UIHandlePendingElicitationRequest) -> Any:
- return to_class(UIHandlePendingElicitationRequest, x)
-
-def permission_request_result_from_dict(s: Any) -> PermissionRequestResult:
- return PermissionRequestResult.from_dict(s)
-
-def permission_request_result_to_dict(x: PermissionRequestResult) -> Any:
- return to_class(PermissionRequestResult, x)
-
-def permission_decision_request_from_dict(s: Any) -> PermissionDecisionRequest:
- return PermissionDecisionRequest.from_dict(s)
-
-def permission_decision_request_to_dict(x: PermissionDecisionRequest) -> Any:
- return to_class(PermissionDecisionRequest, x)
-
def log_result_from_dict(s: Any) -> LogResult:
return LogResult.from_dict(s)
@@ -4087,6 +4881,15 @@ async def create_file(self, params: WorkspacesCreateFileRequest, *, timeout: flo
await self._client.request("session.workspaces.createFile", params_dict, **_timeout_kwargs(timeout))
+class InstructionsApi:
+ def __init__(self, client: "JsonRpcClient", session_id: str):
+ self._client = client
+ self._session_id = session_id
+
+ async def get_sources(self, *, timeout: float | None = None) -> InstructionsGetSourcesResult:
+ return InstructionsGetSourcesResult.from_dict(await self._client.request("session.instructions.getSources", {"sessionId": self._session_id}, **_timeout_kwargs(timeout)))
+
+
# Experimental: this API group is experimental and may change or be removed.
class FleetApi:
def __init__(self, client: "JsonRpcClient", session_id: str):
@@ -4302,6 +5105,7 @@ def __init__(self, client: "JsonRpcClient", session_id: str):
self.name = NameApi(client, session_id)
self.plan = PlanApi(client, session_id)
self.workspaces = WorkspacesApi(client, session_id)
+ self.instructions = InstructionsApi(client, session_id)
self.fleet = FleetApi(client, session_id)
self.agent = AgentApi(client, session_id)
self.skills = SkillsApi(client, session_id)
diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py
index 784b0bb52..7cbff3039 100644
--- a/python/copilot/generated/session_events.py
+++ b/python/copilot/generated/session_events.py
@@ -252,27 +252,27 @@ def to_dict(self) -> dict:
@dataclass
-class SessionStartDataContext:
+class WorkingDirectoryContext:
"Working directory and git context at session start"
cwd: str
git_root: str | None = None
repository: str | None = None
- host_type: SessionStartDataContextHostType | None = None
+ host_type: WorkingDirectoryContextHostType | None = None
branch: str | None = None
head_commit: str | None = None
base_commit: str | None = None
@staticmethod
- def from_dict(obj: Any) -> "SessionStartDataContext":
+ def from_dict(obj: Any) -> "WorkingDirectoryContext":
assert isinstance(obj, dict)
cwd = from_str(obj.get("cwd"))
git_root = from_union([from_none, from_str], obj.get("gitRoot"))
repository = from_union([from_none, from_str], obj.get("repository"))
- host_type = from_union([from_none, lambda x: parse_enum(SessionStartDataContextHostType, x)], obj.get("hostType"))
+ host_type = from_union([from_none, lambda x: parse_enum(WorkingDirectoryContextHostType, x)], obj.get("hostType"))
branch = from_union([from_none, from_str], obj.get("branch"))
head_commit = from_union([from_none, from_str], obj.get("headCommit"))
base_commit = from_union([from_none, from_str], obj.get("baseCommit"))
- return SessionStartDataContext(
+ return WorkingDirectoryContext(
cwd=cwd,
git_root=git_root,
repository=repository,
@@ -290,7 +290,7 @@ def to_dict(self) -> dict:
if self.repository is not None:
result["repository"] = from_union([from_none, from_str], self.repository)
if self.host_type is not None:
- result["hostType"] = from_union([from_none, lambda x: to_enum(SessionStartDataContextHostType, x)], self.host_type)
+ result["hostType"] = from_union([from_none, lambda x: to_enum(WorkingDirectoryContextHostType, x)], self.host_type)
if self.branch is not None:
result["branch"] = from_union([from_none, from_str], self.branch)
if self.head_commit is not None:
@@ -310,7 +310,7 @@ class SessionStartData:
start_time: datetime
selected_model: str | None = None
reasoning_effort: str | None = None
- context: SessionStartDataContext | None = None
+ context: WorkingDirectoryContext | None = None
already_in_use: bool | None = None
remote_steerable: bool | None = None
@@ -324,7 +324,7 @@ def from_dict(obj: Any) -> "SessionStartData":
start_time = from_datetime(obj.get("startTime"))
selected_model = from_union([from_none, from_str], obj.get("selectedModel"))
reasoning_effort = from_union([from_none, from_str], obj.get("reasoningEffort"))
- context = from_union([from_none, SessionStartDataContext.from_dict], obj.get("context"))
+ context = from_union([from_none, WorkingDirectoryContext.from_dict], obj.get("context"))
already_in_use = from_union([from_none, from_bool], obj.get("alreadyInUse"))
remote_steerable = from_union([from_none, from_bool], obj.get("remoteSteerable"))
return SessionStartData(
@@ -352,7 +352,7 @@ 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.context is not None:
- result["context"] = from_union([from_none, lambda x: to_class(SessionStartDataContext, x)], self.context)
+ result["context"] = from_union([from_none, lambda x: to_class(WorkingDirectoryContext, x)], self.context)
if self.already_in_use is not None:
result["alreadyInUse"] = from_union([from_none, from_bool], self.already_in_use)
if self.remote_steerable is not None:
@@ -360,55 +360,6 @@ def to_dict(self) -> dict:
return result
-@dataclass
-class SessionResumeDataContext:
- "Updated working directory and git context at resume time"
- cwd: str
- git_root: str | None = None
- repository: str | None = None
- host_type: SessionResumeDataContextHostType | None = None
- branch: str | None = None
- head_commit: str | None = None
- base_commit: str | None = None
-
- @staticmethod
- def from_dict(obj: Any) -> "SessionResumeDataContext":
- assert isinstance(obj, dict)
- cwd = from_str(obj.get("cwd"))
- git_root = from_union([from_none, from_str], obj.get("gitRoot"))
- repository = from_union([from_none, from_str], obj.get("repository"))
- host_type = from_union([from_none, lambda x: parse_enum(SessionResumeDataContextHostType, x)], obj.get("hostType"))
- branch = from_union([from_none, from_str], obj.get("branch"))
- head_commit = from_union([from_none, from_str], obj.get("headCommit"))
- base_commit = from_union([from_none, from_str], obj.get("baseCommit"))
- return SessionResumeDataContext(
- cwd=cwd,
- git_root=git_root,
- repository=repository,
- host_type=host_type,
- branch=branch,
- head_commit=head_commit,
- base_commit=base_commit,
- )
-
- def to_dict(self) -> dict:
- result: dict = {}
- result["cwd"] = from_str(self.cwd)
- if self.git_root is not None:
- result["gitRoot"] = from_union([from_none, from_str], self.git_root)
- if self.repository is not None:
- result["repository"] = from_union([from_none, from_str], self.repository)
- if self.host_type is not None:
- result["hostType"] = from_union([from_none, lambda x: to_enum(SessionResumeDataContextHostType, x)], self.host_type)
- if self.branch is not None:
- result["branch"] = from_union([from_none, from_str], self.branch)
- if self.head_commit is not None:
- result["headCommit"] = from_union([from_none, from_str], self.head_commit)
- if self.base_commit is not None:
- result["baseCommit"] = from_union([from_none, from_str], self.base_commit)
- return result
-
-
@dataclass
class SessionResumeData:
"Session resume metadata including current context and event count"
@@ -416,7 +367,7 @@ class SessionResumeData:
event_count: float
selected_model: str | None = None
reasoning_effort: str | None = None
- context: SessionResumeDataContext | None = None
+ context: WorkingDirectoryContext | None = None
already_in_use: bool | None = None
remote_steerable: bool | None = None
@@ -427,7 +378,7 @@ def from_dict(obj: Any) -> "SessionResumeData":
event_count = from_float(obj.get("eventCount"))
selected_model = from_union([from_none, from_str], obj.get("selectedModel"))
reasoning_effort = from_union([from_none, from_str], obj.get("reasoningEffort"))
- context = from_union([from_none, SessionResumeDataContext.from_dict], obj.get("context"))
+ context = from_union([from_none, WorkingDirectoryContext.from_dict], obj.get("context"))
already_in_use = from_union([from_none, from_bool], obj.get("alreadyInUse"))
remote_steerable = from_union([from_none, from_bool], obj.get("remoteSteerable"))
return SessionResumeData(
@@ -449,7 +400,7 @@ 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.context is not None:
- result["context"] = from_union([from_none, lambda x: to_class(SessionResumeDataContext, x)], self.context)
+ result["context"] = from_union([from_none, lambda x: to_class(WorkingDirectoryContext, x)], self.context)
if self.already_in_use is not None:
result["alreadyInUse"] = from_union([from_none, from_bool], self.already_in_use)
if self.remote_steerable is not None:
@@ -1038,7 +989,7 @@ def to_dict(self) -> dict:
@dataclass
class SessionContextChangedData:
- "Updated working directory and git context after the change"
+ "Working directory and git context at session start"
cwd: str
git_root: str | None = None
repository: str | None = None
@@ -1484,6 +1435,8 @@ class UserMessageData:
content: str
transformed_content: str | None = None
attachments: list[UserMessageAttachment] | None = None
+ supported_native_document_mime_types: list[str] | None = None
+ native_document_path_fallback_paths: list[str] | None = None
source: str | None = None
agent_mode: UserMessageAgentMode | None = None
interaction_id: str | None = None
@@ -1494,6 +1447,8 @@ def from_dict(obj: Any) -> "UserMessageData":
content = from_str(obj.get("content"))
transformed_content = from_union([from_none, from_str], obj.get("transformedContent"))
attachments = from_union([from_none, lambda x: from_list(UserMessageAttachment.from_dict, x)], obj.get("attachments"))
+ supported_native_document_mime_types = from_union([from_none, lambda x: from_list(from_str, x)], obj.get("supportedNativeDocumentMimeTypes"))
+ native_document_path_fallback_paths = from_union([from_none, lambda x: from_list(from_str, x)], obj.get("nativeDocumentPathFallbackPaths"))
source = from_union([from_none, from_str], obj.get("source"))
agent_mode = from_union([from_none, lambda x: parse_enum(UserMessageAgentMode, x)], obj.get("agentMode"))
interaction_id = from_union([from_none, from_str], obj.get("interactionId"))
@@ -1501,6 +1456,8 @@ def from_dict(obj: Any) -> "UserMessageData":
content=content,
transformed_content=transformed_content,
attachments=attachments,
+ supported_native_document_mime_types=supported_native_document_mime_types,
+ native_document_path_fallback_paths=native_document_path_fallback_paths,
source=source,
agent_mode=agent_mode,
interaction_id=interaction_id,
@@ -1513,6 +1470,10 @@ def to_dict(self) -> dict:
result["transformedContent"] = from_union([from_none, from_str], self.transformed_content)
if self.attachments is not None:
result["attachments"] = from_union([from_none, lambda x: from_list(lambda x: to_class(UserMessageAttachment, x), x)], self.attachments)
+ if self.supported_native_document_mime_types is not None:
+ result["supportedNativeDocumentMimeTypes"] = from_union([from_none, lambda x: from_list(from_str, x)], self.supported_native_document_mime_types)
+ if self.native_document_path_fallback_paths is not None:
+ result["nativeDocumentPathFallbackPaths"] = from_union([from_none, lambda x: from_list(from_str, x)], self.native_document_path_fallback_paths)
if self.source is not None:
result["source"] = from_union([from_none, from_str], self.source)
if self.agent_mode is not None:
@@ -1703,6 +1664,7 @@ class AssistantMessageData:
output_tokens: float | None = None
interaction_id: str | None = None
request_id: str | None = None
+ # Deprecated: this field is deprecated.
parent_tool_call_id: str | None = None
@staticmethod
@@ -1763,6 +1725,7 @@ class AssistantMessageDeltaData:
"Streaming assistant message delta for incremental response updates"
message_id: str
delta_content: str
+ # Deprecated: this field is deprecated.
parent_tool_call_id: str | None = None
@staticmethod
@@ -1922,6 +1885,7 @@ class AssistantUsageData:
initiator: str | None = None
api_call_id: str | None = None
provider_call_id: str | None = None
+ # Deprecated: this field is deprecated.
parent_tool_call_id: str | None = None
quota_snapshots: dict[str, AssistantUsageQuotaSnapshot] | None = None
copilot_usage: AssistantUsageCopilotUsage | None = None
@@ -2060,6 +2024,7 @@ class ToolExecutionStartData:
arguments: Any = None
mcp_server_name: str | None = None
mcp_tool_name: str | None = None
+ # Deprecated: this field is deprecated.
parent_tool_call_id: str | None = None
@staticmethod
@@ -2318,6 +2283,7 @@ class ToolExecutionCompleteData:
result: ToolExecutionCompleteDataResult | None = None
error: ToolExecutionCompleteDataError | None = None
tool_telemetry: dict[str, Any] | None = None
+ # Deprecated: this field is deprecated.
parent_tool_call_id: str | None = None
@staticmethod
@@ -2696,7 +2662,7 @@ def to_dict(self) -> dict:
@dataclass
class SystemMessageData:
- "System or developer message content with role and optional template metadata"
+ "System/developer instruction content with role and optional template metadata"
content: str
role: SystemMessageDataRole
name: str | None = None
@@ -3939,13 +3905,7 @@ def to_dict(self) -> dict:
return result
-class SessionStartDataContextHostType(Enum):
- "Hosting platform type of the repository (github or ado)"
- GITHUB = "github"
- ADO = "ado"
-
-
-class SessionResumeDataContextHostType(Enum):
+class WorkingDirectoryContextHostType(Enum):
"Hosting platform type of the repository (github or ado)"
GITHUB = "github"
ADO = "ado"
diff --git a/python/copilot/session.py b/python/copilot/session.py
index 9552f75b6..43a1c4c5a 100644
--- a/python/copilot/session.py
+++ b/python/copilot/session.py
@@ -43,7 +43,7 @@
UIElicitationSchemaPropertyNumberType,
UIHandlePendingElicitationRequest,
)
-from .generated.rpc import ModelCapabilitiesOverride as _RpcModelCapabilitiesOverride
+from .generated.rpc import ModelCapabilitiesClass as _RpcModelCapabilitiesOverride
from .generated.session_events import (
AssistantMessageData,
CapabilitiesChangedData,
diff --git a/scripts/codegen/csharp.ts b/scripts/codegen/csharp.ts
index f8bcfad1c..d9a4b0f96 100644
--- a/scripts/codegen/csharp.ts
+++ b/scripts/codegen/csharp.ts
@@ -13,6 +13,7 @@ import { promisify } from "util";
import type { JSONSchema7 } from "json-schema";
import {
cloneSchemaForCodegen,
+ fixNullableRequiredRefsInApiSchema,
getApiSchemaPath,
getRpcSchemaTypeName,
getSessionEventsSchemaPath,
@@ -326,7 +327,7 @@ function getOrCreateEnum(parentClassName: string, propName: string, values: stri
const lines: string[] = [];
lines.push(...xmlDocEnumComment(description, ""));
- if (deprecated) lines.push(`[Obsolete]`);
+ if (deprecated) lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
lines.push(`[JsonConverter(typeof(JsonStringEnumConverter<${enumName}>))]`, `public enum ${enumName}`, `{`);
for (const value of values) {
lines.push(` /// The ${escapeXml(value)} variant.`);
@@ -461,7 +462,7 @@ function generateDerivedClass(
const required = new Set(schema.required || []);
lines.push(...xmlDocCommentWithFallback(schema.description, `The ${escapeXml(discriminatorValue)} variant of .`, ""));
- if (isSchemaDeprecated(schema)) lines.push(`[Obsolete]`);
+ if (isSchemaDeprecated(schema)) lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
lines.push(`public partial class ${className} : ${baseClassName}`);
lines.push(`{`);
lines.push(` /// `);
@@ -480,7 +481,7 @@ function generateDerivedClass(
lines.push(...xmlDocPropertyComment((propSchema as JSONSchema7).description, propName, " "));
lines.push(...emitDataAnnotations(propSchema as JSONSchema7, " "));
- if (isSchemaDeprecated(propSchema as JSONSchema7)) lines.push(` [Obsolete]`);
+ if (isSchemaDeprecated(propSchema as JSONSchema7)) lines.push(` [Obsolete("This member is deprecated and will be removed in a future version.")]`);
if (isDurationProperty(propSchema as JSONSchema7)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`);
if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`);
lines.push(` [JsonPropertyName("${propName}")]`);
@@ -504,7 +505,7 @@ function generateNestedClass(
const required = new Set(schema.required || []);
const lines: string[] = [];
lines.push(...xmlDocCommentWithFallback(schema.description, `Nested data type for ${className}.`, ""));
- if (isSchemaDeprecated(schema)) lines.push(`[Obsolete]`);
+ if (isSchemaDeprecated(schema)) lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
lines.push(`public partial class ${className}`, `{`);
for (const [propName, propSchema] of Object.entries(schema.properties || {})) {
@@ -516,7 +517,7 @@ function generateNestedClass(
lines.push(...xmlDocPropertyComment(prop.description, propName, " "));
lines.push(...emitDataAnnotations(prop, " "));
- if (isSchemaDeprecated(prop)) lines.push(` [Obsolete]`);
+ if (isSchemaDeprecated(prop)) lines.push(` [Obsolete("This member is deprecated and will be removed in a future version.")]`);
if (isDurationProperty(prop)) lines.push(` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]`);
if (!isReq) lines.push(` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]`);
lines.push(` [JsonPropertyName("${propName}")]`);
@@ -615,7 +616,7 @@ function generateDataClass(variant: EventVariant, knownTypes: Map.`, ""));
}
if (isSchemaDeprecated(variant.dataSchema)) {
- lines.push(`[Obsolete]`);
+ lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
lines.push(`public partial class ${variant.dataClassName}`, `{`);
@@ -627,7 +628,7 @@ function generateDataClass(variant: EventVariant, knownTypes: Map, cl
lines.push(`[Experimental(Diagnostics.Experimental)]`);
}
if (groupDeprecated) {
- lines.push(`[Obsolete]`);
+ lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
lines.push(`public sealed class ${className}`);
lines.push(`{`);
@@ -1104,7 +1105,7 @@ function emitServerInstanceMethod(
lines.push(`${indent}[Experimental(Diagnostics.Experimental)]`);
}
if (method.deprecated && !groupDeprecated) {
- lines.push(`${indent}[Obsolete]`);
+ lines.push(`${indent}[Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
const sigParams: string[] = [];
@@ -1208,7 +1209,7 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas
lines.push(`${indent}[Experimental(Diagnostics.Experimental)]`);
}
if (method.deprecated && !groupDeprecated) {
- lines.push(`${indent}[Obsolete]`);
+ lines.push(`${indent}[Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
const sigParams: string[] = [];
const bodyAssignments = [`SessionId = _sessionId`];
@@ -1238,7 +1239,7 @@ function emitSessionApiClass(className: string, node: Record, c
const groupExperimental = isNodeFullyExperimental(node);
const groupDeprecated = isNodeFullyDeprecated(node);
const experimentalAttr = groupExperimental ? `[Experimental(Diagnostics.Experimental)]\n` : "";
- const deprecatedAttr = groupDeprecated ? `[Obsolete]\n` : "";
+ const deprecatedAttr = groupDeprecated ? `[Obsolete("This member is deprecated and will be removed in a future version.")]\n` : "";
const subGroups = Object.entries(node).filter(([, v]) => typeof v === "object" && v !== null && !isRpcMethod(v));
const lines = [`/// Provides session-scoped ${displayName} APIs.`, `${experimentalAttr}${deprecatedAttr}public sealed class ${className}`, `{`, ` private readonly JsonRpc _rpc;`, ` private readonly string _sessionId;`, ""];
@@ -1328,7 +1329,7 @@ function emitClientSessionApiRegistration(clientSchema: Record,
lines.push(`[Experimental(Diagnostics.Experimental)]`);
}
if (groupDeprecated) {
- lines.push(`[Obsolete]`);
+ lines.push(`[Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
lines.push(`public interface ${interfaceName}`);
lines.push(`{`);
@@ -1342,7 +1343,7 @@ function emitClientSessionApiRegistration(clientSchema: Record,
lines.push(` [Experimental(Diagnostics.Experimental)]`);
}
if (method.deprecated && !groupDeprecated) {
- lines.push(` [Obsolete]`);
+ lines.push(` [Obsolete("This member is deprecated and will be removed in a future version.")]`);
}
if (hasParams) {
lines.push(` ${taskType} ${clientHandlerMethodName(method.rpcMethod)}(${paramsTypeName(method)} request, CancellationToken cancellationToken = default);`);
@@ -1481,7 +1482,7 @@ internal static class Diagnostics
export async function generateRpc(schemaPath?: string): Promise {
console.log("C#: generating RPC types...");
const resolvedPath = schemaPath ?? (await getApiSchemaPath());
- const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema);
+ const schema = fixNullableRequiredRefsInApiSchema(cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema));
const code = generateRpcCode(schema);
const outPath = await writeGeneratedFile("dotnet/src/Generated/Rpc.cs", code);
console.log(` ✓ ${outPath}`);
diff --git a/scripts/codegen/go.ts b/scripts/codegen/go.ts
index fa21aa703..8f9d40321 100644
--- a/scripts/codegen/go.ts
+++ b/scripts/codegen/go.ts
@@ -13,6 +13,7 @@ import { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } from "
import { promisify } from "util";
import {
cloneSchemaForCodegen,
+ fixNullableRequiredRefsInApiSchema,
getApiSchemaPath,
getRpcSchemaTypeName,
getSessionEventsSchemaPath,
@@ -968,7 +969,7 @@ async function generateRpc(schemaPath?: string): Promise {
console.log("Go: generating RPC types...");
const resolvedPath = schemaPath ?? (await getApiSchemaPath());
- const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema);
+ const schema = fixNullableRequiredRefsInApiSchema(cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema));
const allMethods = [
...collectRpcMethods(schema.server || {}),
diff --git a/scripts/codegen/python.ts b/scripts/codegen/python.ts
index bb1f56e0d..175c5175b 100644
--- a/scripts/codegen/python.ts
+++ b/scripts/codegen/python.ts
@@ -12,6 +12,7 @@ import type { JSONSchema7 } from "json-schema";
import { fileURLToPath } from "url";
import {
cloneSchemaForCodegen,
+ fixNullableRequiredRefsInApiSchema,
getApiSchemaPath,
getRpcSchemaTypeName,
getSessionEventsSchemaPath,
@@ -184,6 +185,157 @@ function collapsePlaceholderPythonDataclasses(code: string): string {
return code.replace(/\n{3,}/g, "\n\n");
}
+/**
+ * Reorder Python class/enum definitions so forward references are resolved.
+ * Quicktype may emit classes in an order where a class references another
+ * that hasn't been defined yet, causing NameError at import time.
+ * This performs a topological sort of type definitions while preserving
+ * the relative position of non-class blocks (functions, standalone code).
+ */
+function reorderPythonForwardRefs(code: string): string {
+ // Split code into top-level blocks. Each block starts at an unindented
+ // line that begins a class, decorated class, enum, or function definition.
+ const lines = code.split("\n");
+
+ interface Block {
+ name: string;
+ code: string;
+ isType: boolean; // true for class/enum definitions
+ }
+
+ const blocks: Block[] = [];
+ let currentLines: string[] = [];
+ let currentName: string | null = null;
+ let isType = false;
+
+ function flushBlock() {
+ if (currentLines.length === 0) return;
+ const blockCode = currentLines.join("\n");
+ blocks.push({
+ name: currentName ?? `__anon_${blocks.length}`,
+ code: blockCode,
+ isType,
+ });
+ currentLines = [];
+ currentName = null;
+ isType = false;
+ }
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+ const isTopLevel = line.length > 0 && line[0] !== " " && line[0] !== "\t";
+
+ if (isTopLevel) {
+ const classMatch = line.match(/^class\s+(\w+)/);
+ const defMatch = line.match(/^def\s+(\w+)/);
+ const decoratorMatch = line === "@dataclass";
+ const commentMatch = line.startsWith("# ");
+
+ if (classMatch) {
+ // If previous block was just a decorator waiting for a class, merge
+ if (currentLines.length > 0 && currentName === null && isType) {
+ // This is the class line following @dataclass
+ currentName = classMatch[1];
+ currentLines.push(line);
+ continue;
+ }
+ flushBlock();
+ currentLines = [line];
+ currentName = classMatch[1];
+ isType = true;
+ } else if (decoratorMatch) {
+ flushBlock();
+ currentLines = [line];
+ isType = true;
+ } else if (defMatch) {
+ flushBlock();
+ currentLines = [line];
+ currentName = defMatch[1];
+ isType = false;
+ } else if (commentMatch && currentLines.length === 0) {
+ // Standalone comment — attach to next block
+ currentLines = [line];
+ } else {
+ currentLines.push(line);
+ }
+ } else {
+ currentLines.push(line);
+ }
+ }
+ flushBlock();
+
+ if (blocks.length === 0) return code;
+
+ // Collect all type names (classes and enums)
+ const typeNames = new Set(blocks.filter((b) => b.isType).map((b) => b.name));
+ if (typeNames.size === 0) return code;
+
+ // Build dependency graph: for each type block, find references to other type names
+ const deps = new Map>();
+ for (const block of blocks) {
+ if (!block.isType) continue;
+ const blockDeps = new Set();
+ for (const tn of typeNames) {
+ if (tn === block.name) continue;
+ if (new RegExp(`\\b${tn}\\b`).test(block.code)) {
+ blockDeps.add(tn);
+ }
+ }
+ deps.set(block.name, blockDeps);
+ }
+
+ // Kahn's algorithm for topological sort
+ const inDegree = new Map();
+ for (const tn of typeNames) inDegree.set(tn, deps.get(tn)?.size ?? 0);
+
+ const dependents = new Map();
+ for (const tn of typeNames) dependents.set(tn, []);
+ for (const [name, d] of deps) {
+ for (const dep of d) {
+ dependents.get(dep)!.push(name);
+ }
+ }
+
+ const queue: string[] = [];
+ for (const [tn, deg] of inDegree) {
+ if (deg === 0) queue.push(tn);
+ }
+
+ const sorted: string[] = [];
+ while (queue.length > 0) {
+ const node = queue.shift()!;
+ sorted.push(node);
+ for (const dep of dependents.get(node) ?? []) {
+ const newDeg = inDegree.get(dep)! - 1;
+ inDegree.set(dep, newDeg);
+ if (newDeg === 0) queue.push(dep);
+ }
+ }
+
+ // If there are cycles, keep remaining nodes in original order
+ for (const block of blocks) {
+ if (block.isType && !sorted.includes(block.name)) {
+ sorted.push(block.name);
+ }
+ }
+
+ // Rebuild: place type blocks in sorted order at the positions
+ // where type blocks originally appeared
+ const typeBlockMap = new Map(blocks.filter((b) => b.isType).map((b) => [b.name, b]));
+ let sortIdx = 0;
+ const result: string[] = [];
+ for (const block of blocks) {
+ if (block.isType) {
+ result.push(typeBlockMap.get(sorted[sortIdx])!.code);
+ sortIdx++;
+ } else {
+ result.push(block.code);
+ }
+ }
+
+ return result.join("\n");
+}
+
function normalizePythonDataclassBlock(block: string, name: string): string {
return block
.replace(/^@dataclass\r?\nclass\s+\w+:/, "@dataclass\nclass:")
@@ -1395,7 +1547,7 @@ async function generateRpc(schemaPath?: string): Promise {
const { FetchingJSONSchemaStore, InputData, JSONSchemaInput, quicktype } = await import("quicktype-core");
const resolvedPath = schemaPath ?? (await getApiSchemaPath());
- const schema = cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema);
+ const schema = fixNullableRequiredRefsInApiSchema(cloneSchemaForCodegen(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema));
const allMethods = [
...collectRpcMethods(schema.server || {}),
@@ -1482,6 +1634,10 @@ async function generateRpc(schemaPath?: string): Promise {
typesCode = modernizePython(typesCode);
typesCode = collapsePlaceholderPythonDataclasses(typesCode);
+ // Reorder class/enum definitions to resolve forward references.
+ // Quicktype may emit classes before their dependencies are defined.
+ typesCode = reorderPythonForwardRefs(typesCode);
+
// Strip quicktype's import block and preamble — we provide our own unified header.
// The preamble ends just before the first helper function (e.g. "def from_str")
// or class definition.
diff --git a/scripts/codegen/typescript.ts b/scripts/codegen/typescript.ts
index 8cc3e4078..1aba7384c 100644
--- a/scripts/codegen/typescript.ts
+++ b/scripts/codegen/typescript.ts
@@ -11,6 +11,7 @@ import type { JSONSchema7 } from "json-schema";
import { compile } from "json-schema-to-typescript";
import {
getApiSchemaPath,
+ fixNullableRequiredRefsInApiSchema,
getRpcSchemaTypeName,
getSessionEventsSchemaPath,
normalizeSchemaTitles,
@@ -320,7 +321,7 @@ async function generateRpc(schemaPath?: string): Promise {
console.log("TypeScript: generating RPC types...");
const resolvedPath = schemaPath ?? (await getApiSchemaPath());
- const schema = JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema;
+ const schema = fixNullableRequiredRefsInApiSchema(JSON.parse(await fs.readFile(resolvedPath, "utf-8")) as ApiSchema);
const lines: string[] = [];
lines.push(`/**
diff --git a/scripts/codegen/utils.ts b/scripts/codegen/utils.ts
index d6083adec..bc144bf75 100644
--- a/scripts/codegen/utils.ts
+++ b/scripts/codegen/utils.ts
@@ -128,6 +128,78 @@ export function postProcessSchema(schema: JSONSchema7): JSONSchema7 {
return processed;
}
+/**
+ * Normalize schema defects where a required property with a `$ref` to an object type
+ * has a description explicitly mentioning "null" as a valid value.
+ *
+ * In JSON Schema, `required` only means the key must be present — it doesn't prevent
+ * the value from being null. Some schemas mark properties as required but describe them
+ * as nullable (e.g., "Currently selected agent, or null if using the default").
+ *
+ * This function converts such properties from:
+ * `{ "$ref": "#/definitions/Foo", "description": "...null..." }`
+ * to:
+ * `{ "anyOf": [{ "$ref": "#/definitions/Foo" }, { "type": "null" }], "description": "...null..." }`
+ *
+ * This makes all downstream codegen (Go, C#, Python/quicktype, TypeScript) correctly
+ * emit nullable/optional types without per-language heuristics.
+ */
+export function normalizeNullableRequiredRefs(schema: JSONSchema7): JSONSchema7 {
+ if (typeof schema !== "object" || schema === null) return schema;
+
+ const processed = { ...schema };
+
+ if (processed.properties && processed.required) {
+ const requiredSet = new Set(processed.required);
+ const newProps: Record = {};
+ const newRequired = [...processed.required];
+
+ for (const [key, value] of Object.entries(processed.properties)) {
+ if (typeof value !== "object" || value === null) {
+ newProps[key] = value;
+ continue;
+ }
+ const prop = value as JSONSchema7;
+ if (
+ requiredSet.has(key) &&
+ prop.$ref &&
+ typeof prop.description === "string" &&
+ /\bnull\b/i.test(prop.description)
+ ) {
+ // Convert to anyOf: [$ref, null] and remove from required
+ const { $ref, ...rest } = prop;
+ newProps[key] = {
+ ...rest,
+ anyOf: [{ $ref }, { type: "null" as const }],
+ };
+ const idx = newRequired.indexOf(key);
+ if (idx !== -1) newRequired.splice(idx, 1);
+ } else {
+ newProps[key] = normalizeNullableRequiredRefs(prop);
+ }
+ }
+
+ processed.properties = newProps;
+ processed.required = newRequired;
+ }
+
+ // Recurse into nested schemas
+ if (processed.items) {
+ if (typeof processed.items === "object" && !Array.isArray(processed.items)) {
+ processed.items = normalizeNullableRequiredRefs(processed.items as JSONSchema7);
+ }
+ }
+ for (const combiner of ["anyOf", "allOf", "oneOf"] as const) {
+ if (processed[combiner]) {
+ processed[combiner] = processed[combiner]!.map((item) =>
+ typeof item === "object" ? normalizeNullableRequiredRefs(item as JSONSchema7) : item
+ ) as JSONSchema7Definition[];
+ }
+ }
+
+ return processed;
+}
+
// ── File output ─────────────────────────────────────────────────────────────
export async function writeGeneratedFile(relativePath: string, content: string): Promise {
@@ -452,6 +524,52 @@ export function normalizeApiSchema(schema: ApiSchema): ApiSchema {
};
}
+/**
+ * Apply `normalizeNullableRequiredRefs` to every JSON Schema reachable from the API schema
+ * (method params, results, and shared definitions). Call after `cloneSchemaForCodegen` to
+ * fix schema defects before any per-language codegen runs.
+ */
+export function fixNullableRequiredRefsInApiSchema(schema: ApiSchema): ApiSchema {
+ function walkApiNode(node: Record | undefined): Record | undefined {
+ if (!node) return undefined;
+ const result: Record = {};
+ for (const [key, value] of Object.entries(node)) {
+ if (isRpcMethod(value)) {
+ const method = value as RpcMethod;
+ result[key] = {
+ ...method,
+ params: method.params ? normalizeNullableRequiredRefs(method.params) : method.params,
+ result: method.result ? normalizeNullableRequiredRefs(method.result) : method.result,
+ };
+ } else if (typeof value === "object" && value !== null) {
+ result[key] = walkApiNode(value as Record);
+ } else {
+ result[key] = value;
+ }
+ }
+ return result;
+ }
+
+ function normalizeDefs(defs: Record | undefined): Record | undefined {
+ if (!defs) return undefined;
+ return Object.fromEntries(
+ Object.entries(defs).map(([key, value]) => [
+ key,
+ typeof value === "object" && value !== null ? normalizeNullableRequiredRefs(value as JSONSchema7) : value,
+ ])
+ );
+ }
+
+ return {
+ ...schema,
+ definitions: normalizeDefs(schema.definitions),
+ $defs: normalizeDefs(schema.$defs),
+ server: walkApiNode(schema.server),
+ session: walkApiNode(schema.session),
+ clientSession: walkApiNode(schema.clientSession),
+ };
+}
+
/** Returns true when every leaf RPC method inside `node` is marked experimental. */
export function isNodeFullyExperimental(node: Record): boolean {
const methods: RpcMethod[] = [];
diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json
index 2c82d7b87..dad61dfd3 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.30",
+ "@github/copilot": "^1.0.32-1",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",
@@ -462,27 +462,27 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.30.tgz",
- "integrity": "sha512-JYZNMM6hteAE6tIMbHobRjpAaXzvqeeglXgGlDCr26rRq3K6h5ul2GN27qzhMBaWyujUQN402KLKdrhDPqcL7A==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.32-1.tgz",
+ "integrity": "sha512-uJgZWkd+gYS6t8NeWgZd+KDlQ41RFvAydOPdJqMDdB8aBwJYKQA75AVQzJyIne/CaMmv2Cy24X+IeRsMXvg+YA==",
"dev": true,
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.30",
- "@github/copilot-darwin-x64": "1.0.30",
- "@github/copilot-linux-arm64": "1.0.30",
- "@github/copilot-linux-x64": "1.0.30",
- "@github/copilot-win32-arm64": "1.0.30",
- "@github/copilot-win32-x64": "1.0.30"
+ "@github/copilot-darwin-arm64": "1.0.32-1",
+ "@github/copilot-darwin-x64": "1.0.32-1",
+ "@github/copilot-linux-arm64": "1.0.32-1",
+ "@github/copilot-linux-x64": "1.0.32-1",
+ "@github/copilot-win32-arm64": "1.0.32-1",
+ "@github/copilot-win32-x64": "1.0.32-1"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.30.tgz",
- "integrity": "sha512-qhLMhAY7nskG6yabbsWSqErxPWcZLX1ixJBdQX3RLqgw5dyNvZRNzG2evUnABo5bqgndztsFXjE3u4XtfX0WkA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-MGz9kKJYqrfZ94DOVsKy8c0sTFn1Gax60hM3TjMt6K+Tt7n8vGhrpBn+KjFYOb+6+r7fp3E7fc6tTtwjgaURVw==",
"cpu": [
"arm64"
],
@@ -497,9 +497,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.30.tgz",
- "integrity": "sha512-nsjGRt1jLBzCaVd6eb3ok75zqePr8eU8GSTqu1KVf5KUrnvvfIlsvESkEAE8l+lkR14f7SGQLfMJ2EEbcJMGcg==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.32-1.tgz",
+ "integrity": "sha512-HSLJXMVk2yf6Xb6NhNxEYvD57hBGdWs5zQ7EOHrFYO+qA5/iD4JVGgQNg7sS88+qsTR5PtEcxwbtQPid1KZJnQ==",
"cpu": [
"x64"
],
@@ -514,9 +514,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.30.tgz",
- "integrity": "sha512-7wOrOKm9MHnglyzzGeZnXSkfRi4sXB2Db7rK/CgUenxS+dwwIuXhT4rgkH/DIOiDbGCxYjigICxln28Jvbs+cA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-XBiX4947+ygPugwsZrrVOwftIWWASoknq1FzehIpj7BqPxjwTpzDXPDJNleHf+6a1cGm8cUutDn/wslHjJEW9A==",
"cpu": [
"arm64"
],
@@ -531,9 +531,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.30.tgz",
- "integrity": "sha512-OSJtP7mV9vnDzGFjBkI3sgbNOcxsRcq7vXrT4PNrjJw4Mc71aaW55hc5F1j2fElfGWIb+Jubm3AB8nb6AoufnA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.32-1.tgz",
+ "integrity": "sha512-iJkcWKSoaDY5GKtOZtoZV5YhuOqvVSdENashNKjXzkIoFN0mqonIhsbAv3OB2Kr34ZwoQF3CfNoOCNBs2tg8pg==",
"cpu": [
"x64"
],
@@ -548,9 +548,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.30.tgz",
- "integrity": "sha512-5nCz/+9VWJdNvW2uRYeMmnRdQq/gpuSlmYMvRv8fIsFF8KH0mdJndJn8xN6GeJtx0fKJrLzgKqJHWdgb5MtLgA==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.32-1.tgz",
+ "integrity": "sha512-U/lfmWAqOIxucqotmsOsJtOjfAhNIYAFeqxyaKo+V35YkurXZGTNjB2YxqUlmKm/7fuOgAACHKvrK+tWs+Mlvg==",
"cpu": [
"arm64"
],
@@ -565,9 +565,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.30",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.30.tgz",
- "integrity": "sha512-tJvgCsWLJVQvHLvFyQZ0P5MQ7YGX51/bl9kbXDUFCGATtPpELul3NyHWwEYGjRv+VDPvhFxjbf+V7Bf/VzYZ7w==",
+ "version": "1.0.32-1",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.32-1.tgz",
+ "integrity": "sha512-oSNG9nRHsyTdi2miBfti4egT+CHPGu0QTXXUasISsfwhex6SS4qeVFe8mt8/clnTlyJD9N7EDgABDduSYQv87g==",
"cpu": [
"x64"
],
diff --git a/test/harness/package.json b/test/harness/package.json
index 94fe9d8c5..37bb8031a 100644
--- a/test/harness/package.json
+++ b/test/harness/package.json
@@ -11,7 +11,7 @@
"test": "vitest run"
},
"devDependencies": {
- "@github/copilot": "^1.0.30",
+ "@github/copilot": "^1.0.32-1",
"@modelcontextprotocol/sdk": "^1.26.0",
"@types/node": "^25.3.3",
"openai": "^6.17.0",